blob: bfc402d4760976b12abf30033fa5c3bb3230c26f [file] [log] [blame]
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001/*
2 * Copyright © 2017 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25#include <linux/perf_event.h>
26#include <linux/pm_runtime.h>
27
28#include "i915_drv.h"
29#include "i915_pmu.h"
30#include "intel_ringbuffer.h"
31
32/* Frequency for the sampling timer for events which need it. */
33#define FREQUENCY 200
34#define PERIOD max_t(u64, 10000, NSEC_PER_SEC / FREQUENCY)
35
36#define ENGINE_SAMPLE_MASK \
37 (BIT(I915_SAMPLE_BUSY) | \
38 BIT(I915_SAMPLE_WAIT) | \
39 BIT(I915_SAMPLE_SEMA))
40
41#define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
42
Chris Wilson141a0892017-11-23 12:34:31 +000043static cpumask_t i915_pmu_cpumask;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +000044
45static u8 engine_config_sample(u64 config)
46{
47 return config & I915_PMU_SAMPLE_MASK;
48}
49
50static u8 engine_event_sample(struct perf_event *event)
51{
52 return engine_config_sample(event->attr.config);
53}
54
55static u8 engine_event_class(struct perf_event *event)
56{
57 return (event->attr.config >> I915_PMU_CLASS_SHIFT) & 0xff;
58}
59
60static u8 engine_event_instance(struct perf_event *event)
61{
62 return (event->attr.config >> I915_PMU_SAMPLE_BITS) & 0xff;
63}
64
65static bool is_engine_config(u64 config)
66{
67 return config < __I915_PMU_OTHER(0);
68}
69
70static unsigned int config_enabled_bit(u64 config)
71{
72 if (is_engine_config(config))
73 return engine_config_sample(config);
74 else
75 return ENGINE_SAMPLE_BITS + (config - __I915_PMU_OTHER(0));
76}
77
78static u64 config_enabled_mask(u64 config)
79{
80 return BIT_ULL(config_enabled_bit(config));
81}
82
83static bool is_engine_event(struct perf_event *event)
84{
85 return is_engine_config(event->attr.config);
86}
87
88static unsigned int event_enabled_bit(struct perf_event *event)
89{
90 return config_enabled_bit(event->attr.config);
91}
92
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +000093static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
94{
95 u64 enable;
96
97 /*
98 * Only some counters need the sampling timer.
99 *
100 * We start with a bitmask of all currently enabled events.
101 */
102 enable = i915->pmu.enable;
103
104 /*
105 * Mask out all the ones which do not need the timer, or in
106 * other words keep all the ones that could need the timer.
107 */
108 enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
109 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
110 ENGINE_SAMPLE_MASK;
111
112 /*
113 * When the GPU is idle per-engine counters do not need to be
114 * running so clear those bits out.
115 */
116 if (!gpu_active)
117 enable &= ~ENGINE_SAMPLE_MASK;
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000118 /*
119 * Also there is software busyness tracking available we do not
120 * need the timer for I915_SAMPLE_BUSY counter.
Tvrtko Ursulincf669b42017-11-29 10:28:05 +0000121 *
122 * Use RCS as proxy for all engines.
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000123 */
Tvrtko Ursulincf669b42017-11-29 10:28:05 +0000124 else if (intel_engine_supports_stats(i915->engine[RCS]))
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000125 enable &= ~BIT(I915_SAMPLE_BUSY);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000126
127 /*
128 * If some bits remain it means we need the sampling timer running.
129 */
130 return enable;
131}
132
133void i915_pmu_gt_parked(struct drm_i915_private *i915)
134{
135 if (!i915->pmu.base.event_init)
136 return;
137
138 spin_lock_irq(&i915->pmu.lock);
139 /*
140 * Signal sampling timer to stop if only engine events are enabled and
141 * GPU went idle.
142 */
143 i915->pmu.timer_enabled = pmu_needs_timer(i915, false);
144 spin_unlock_irq(&i915->pmu.lock);
145}
146
147static void __i915_pmu_maybe_start_timer(struct drm_i915_private *i915)
148{
149 if (!i915->pmu.timer_enabled && pmu_needs_timer(i915, true)) {
150 i915->pmu.timer_enabled = true;
151 hrtimer_start_range_ns(&i915->pmu.timer,
152 ns_to_ktime(PERIOD), 0,
153 HRTIMER_MODE_REL_PINNED);
154 }
155}
156
157void i915_pmu_gt_unparked(struct drm_i915_private *i915)
158{
159 if (!i915->pmu.base.event_init)
160 return;
161
162 spin_lock_irq(&i915->pmu.lock);
163 /*
164 * Re-enable sampling timer when GPU goes active.
165 */
166 __i915_pmu_maybe_start_timer(i915);
167 spin_unlock_irq(&i915->pmu.lock);
168}
169
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000170static bool grab_forcewake(struct drm_i915_private *i915, bool fw)
171{
172 if (!fw)
173 intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
174
175 return true;
176}
177
178static void
179update_sample(struct i915_pmu_sample *sample, u32 unit, u32 val)
180{
Tvrtko Ursulin8ee4f192017-11-24 09:49:59 +0000181 sample->cur += mul_u32_u32(val, unit);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000182}
183
184static void engines_sample(struct drm_i915_private *dev_priv)
185{
186 struct intel_engine_cs *engine;
187 enum intel_engine_id id;
188 bool fw = false;
189
190 if ((dev_priv->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
191 return;
192
193 if (!dev_priv->gt.awake)
194 return;
195
196 if (!intel_runtime_pm_get_if_in_use(dev_priv))
197 return;
198
199 for_each_engine(engine, dev_priv, id) {
200 u32 current_seqno = intel_engine_get_seqno(engine);
201 u32 last_seqno = intel_engine_last_submit(engine);
202 u32 val;
203
204 val = !i915_seqno_passed(current_seqno, last_seqno);
205
206 update_sample(&engine->pmu.sample[I915_SAMPLE_BUSY],
207 PERIOD, val);
208
209 if (val && (engine->pmu.enable &
210 (BIT(I915_SAMPLE_WAIT) | BIT(I915_SAMPLE_SEMA)))) {
211 fw = grab_forcewake(dev_priv, fw);
212
213 val = I915_READ_FW(RING_CTL(engine->mmio_base));
214 } else {
215 val = 0;
216 }
217
218 update_sample(&engine->pmu.sample[I915_SAMPLE_WAIT],
219 PERIOD, !!(val & RING_WAIT));
220
221 update_sample(&engine->pmu.sample[I915_SAMPLE_SEMA],
222 PERIOD, !!(val & RING_WAIT_SEMAPHORE));
223 }
224
225 if (fw)
226 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
227
228 intel_runtime_pm_put(dev_priv);
229}
230
231static void frequency_sample(struct drm_i915_private *dev_priv)
232{
233 if (dev_priv->pmu.enable &
234 config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
235 u32 val;
236
237 val = dev_priv->gt_pm.rps.cur_freq;
238 if (dev_priv->gt.awake &&
239 intel_runtime_pm_get_if_in_use(dev_priv)) {
240 val = intel_get_cagf(dev_priv,
241 I915_READ_NOTRACE(GEN6_RPSTAT1));
242 intel_runtime_pm_put(dev_priv);
243 }
244
245 update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
246 1, intel_gpu_freq(dev_priv, val));
247 }
248
249 if (dev_priv->pmu.enable &
250 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
251 update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_REQ], 1,
252 intel_gpu_freq(dev_priv,
253 dev_priv->gt_pm.rps.cur_freq));
254 }
255}
256
257static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
258{
259 struct drm_i915_private *i915 =
260 container_of(hrtimer, struct drm_i915_private, pmu.timer);
261
Tvrtko Ursulin8ee4f192017-11-24 09:49:59 +0000262 if (!READ_ONCE(i915->pmu.timer_enabled))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000263 return HRTIMER_NORESTART;
264
265 engines_sample(i915);
266 frequency_sample(i915);
267
268 hrtimer_forward_now(hrtimer, ns_to_ktime(PERIOD));
269 return HRTIMER_RESTART;
270}
271
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000272static u64 count_interrupts(struct drm_i915_private *i915)
273{
274 /* open-coded kstat_irqs() */
275 struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq);
276 u64 sum = 0;
277 int cpu;
278
279 if (!desc || !desc->kstat_irqs)
280 return 0;
281
282 for_each_possible_cpu(cpu)
283 sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
284
285 return sum;
286}
287
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000288static void engine_event_destroy(struct perf_event *event)
289{
290 struct drm_i915_private *i915 =
291 container_of(event->pmu, typeof(*i915), pmu.base);
292 struct intel_engine_cs *engine;
293
294 engine = intel_engine_lookup_user(i915,
295 engine_event_class(event),
296 engine_event_instance(event));
297 if (WARN_ON_ONCE(!engine))
298 return;
299
300 if (engine_event_sample(event) == I915_SAMPLE_BUSY &&
301 intel_engine_supports_stats(engine))
302 intel_disable_engine_stats(engine);
303}
304
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000305static void i915_pmu_event_destroy(struct perf_event *event)
306{
307 WARN_ON(event->parent);
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000308
309 if (is_engine_event(event))
310 engine_event_destroy(event);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000311}
312
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000313static int
314engine_event_status(struct intel_engine_cs *engine,
315 enum drm_i915_pmu_engine_sample sample)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000316{
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000317 switch (sample) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000318 case I915_SAMPLE_BUSY:
319 case I915_SAMPLE_WAIT:
320 break;
321 case I915_SAMPLE_SEMA:
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000322 if (INTEL_GEN(engine->i915) < 6)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000323 return -ENODEV;
324 break;
325 default:
326 return -ENOENT;
327 }
328
329 return 0;
330}
331
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000332static int
333config_status(struct drm_i915_private *i915, u64 config)
334{
335 switch (config) {
336 case I915_PMU_ACTUAL_FREQUENCY:
337 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
338 /* Requires a mutex for sampling! */
339 return -ENODEV;
340 /* Fall-through. */
341 case I915_PMU_REQUESTED_FREQUENCY:
342 if (INTEL_GEN(i915) < 6)
343 return -ENODEV;
344 break;
345 case I915_PMU_INTERRUPTS:
346 break;
347 case I915_PMU_RC6_RESIDENCY:
348 if (!HAS_RC6(i915))
349 return -ENODEV;
350 break;
351 default:
352 return -ENOENT;
353 }
354
355 return 0;
356}
357
358static int engine_event_init(struct perf_event *event)
359{
360 struct drm_i915_private *i915 =
361 container_of(event->pmu, typeof(*i915), pmu.base);
362 struct intel_engine_cs *engine;
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000363 u8 sample;
364 int ret;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000365
366 engine = intel_engine_lookup_user(i915, engine_event_class(event),
367 engine_event_instance(event));
368 if (!engine)
369 return -ENODEV;
370
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000371 sample = engine_event_sample(event);
372 ret = engine_event_status(engine, sample);
373 if (ret)
374 return ret;
375
376 if (sample == I915_SAMPLE_BUSY && intel_engine_supports_stats(engine))
377 ret = intel_enable_engine_stats(engine);
378
379 return ret;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000380}
381
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000382static int i915_pmu_event_init(struct perf_event *event)
383{
384 struct drm_i915_private *i915 =
385 container_of(event->pmu, typeof(*i915), pmu.base);
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000386 int ret;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000387
388 if (event->attr.type != event->pmu->type)
389 return -ENOENT;
390
391 /* unsupported modes and filters */
392 if (event->attr.sample_period) /* no sampling */
393 return -EINVAL;
394
395 if (has_branch_stack(event))
396 return -EOPNOTSUPP;
397
398 if (event->cpu < 0)
399 return -EINVAL;
400
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000401 /* only allow running on one cpu at a time */
402 if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask))
Tvrtko Ursulin00a79722017-11-28 10:55:15 +0000403 return -EINVAL;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000404
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000405 if (is_engine_event(event))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000406 ret = engine_event_init(event);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000407 else
408 ret = config_status(i915, event->attr.config);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000409 if (ret)
410 return ret;
411
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000412 if (!event->parent)
413 event->destroy = i915_pmu_event_destroy;
414
415 return 0;
416}
417
Tvrtko Ursulin1fe699e2018-02-06 18:33:11 +0000418static u64 get_rc6(struct drm_i915_private *i915, bool locked)
419{
420 unsigned long flags;
421 u64 val;
422
423 if (intel_runtime_pm_get_if_in_use(i915)) {
424 val = intel_rc6_residency_ns(i915, IS_VALLEYVIEW(i915) ?
425 VLV_GT_RENDER_RC6 :
426 GEN6_GT_GFX_RC6);
427
428 if (HAS_RC6p(i915))
429 val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p);
430
431 if (HAS_RC6pp(i915))
432 val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp);
433
434 intel_runtime_pm_put(i915);
435
436 /*
437 * If we are coming back from being runtime suspended we must
438 * be careful not to report a larger value than returned
439 * previously.
440 */
441
442 if (!locked)
443 spin_lock_irqsave(&i915->pmu.lock, flags);
444
445 if (val >= i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) {
446 i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0;
447 i915->pmu.sample[__I915_SAMPLE_RC6].cur = val;
448 } else {
449 val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur;
450 }
451
452 if (!locked)
453 spin_unlock_irqrestore(&i915->pmu.lock, flags);
454 } else {
455 struct pci_dev *pdev = i915->drm.pdev;
456 struct device *kdev = &pdev->dev;
457 unsigned long flags2;
458
459 /*
460 * We are runtime suspended.
461 *
462 * Report the delta from when the device was suspended to now,
463 * on top of the last known real value, as the approximated RC6
464 * counter value.
465 */
466 if (!locked)
467 spin_lock_irqsave(&i915->pmu.lock, flags);
468
469 spin_lock_irqsave(&kdev->power.lock, flags2);
470
471 if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur)
472 i915->pmu.suspended_jiffies_last =
473 kdev->power.suspended_jiffies;
474
475 val = kdev->power.suspended_jiffies -
476 i915->pmu.suspended_jiffies_last;
477 val += jiffies - kdev->power.accounting_timestamp;
478
479 spin_unlock_irqrestore(&kdev->power.lock, flags2);
480
481 val = jiffies_to_nsecs(val);
482 val += i915->pmu.sample[__I915_SAMPLE_RC6].cur;
483 i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
484
485 if (!locked)
486 spin_unlock_irqrestore(&i915->pmu.lock, flags);
487 }
488
489 return val;
490}
491
492static u64 __i915_pmu_event_read(struct perf_event *event, bool locked)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000493{
494 struct drm_i915_private *i915 =
495 container_of(event->pmu, typeof(*i915), pmu.base);
496 u64 val = 0;
497
498 if (is_engine_event(event)) {
499 u8 sample = engine_event_sample(event);
500 struct intel_engine_cs *engine;
501
502 engine = intel_engine_lookup_user(i915,
503 engine_event_class(event),
504 engine_event_instance(event));
505
506 if (WARN_ON_ONCE(!engine)) {
507 /* Do nothing */
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000508 } else if (sample == I915_SAMPLE_BUSY &&
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000509 intel_engine_supports_stats(engine)) {
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000510 val = ktime_to_ns(intel_engine_get_busy_time(engine));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000511 } else {
512 val = engine->pmu.sample[sample].cur;
513 }
514 } else {
515 switch (event->attr.config) {
516 case I915_PMU_ACTUAL_FREQUENCY:
517 val =
518 div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_ACT].cur,
519 FREQUENCY);
520 break;
521 case I915_PMU_REQUESTED_FREQUENCY:
522 val =
523 div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_REQ].cur,
524 FREQUENCY);
525 break;
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000526 case I915_PMU_INTERRUPTS:
527 val = count_interrupts(i915);
528 break;
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000529 case I915_PMU_RC6_RESIDENCY:
Tvrtko Ursulin1fe699e2018-02-06 18:33:11 +0000530 val = get_rc6(i915, locked);
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000531 break;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000532 }
533 }
534
535 return val;
536}
537
538static void i915_pmu_event_read(struct perf_event *event)
539{
540 struct hw_perf_event *hwc = &event->hw;
541 u64 prev, new;
542
543again:
544 prev = local64_read(&hwc->prev_count);
Tvrtko Ursulin1fe699e2018-02-06 18:33:11 +0000545 new = __i915_pmu_event_read(event, false);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000546
547 if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
548 goto again;
549
550 local64_add(new - prev, &event->count);
551}
552
553static void i915_pmu_enable(struct perf_event *event)
554{
555 struct drm_i915_private *i915 =
556 container_of(event->pmu, typeof(*i915), pmu.base);
557 unsigned int bit = event_enabled_bit(event);
558 unsigned long flags;
559
560 spin_lock_irqsave(&i915->pmu.lock, flags);
561
562 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000563 * Update the bitmask of enabled events and increment
564 * the event reference counter.
565 */
566 GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
567 GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
568 i915->pmu.enable |= BIT_ULL(bit);
569 i915->pmu.enable_count[bit]++;
570
571 /*
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000572 * Start the sampling timer if needed and not already enabled.
573 */
574 __i915_pmu_maybe_start_timer(i915);
575
576 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000577 * For per-engine events the bitmask and reference counting
578 * is stored per engine.
579 */
580 if (is_engine_event(event)) {
581 u8 sample = engine_event_sample(event);
582 struct intel_engine_cs *engine;
583
584 engine = intel_engine_lookup_user(i915,
585 engine_event_class(event),
586 engine_event_instance(event));
587 GEM_BUG_ON(!engine);
588 engine->pmu.enable |= BIT(sample);
589
590 GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
591 GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000592 engine->pmu.enable_count[sample]++;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000593 }
594
595 /*
596 * Store the current counter value so we can report the correct delta
597 * for all listeners. Even when the event was already enabled and has
598 * an existing non-zero value.
599 */
Tvrtko Ursulin1fe699e2018-02-06 18:33:11 +0000600 local64_set(&event->hw.prev_count, __i915_pmu_event_read(event, true));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000601
602 spin_unlock_irqrestore(&i915->pmu.lock, flags);
603}
604
605static void i915_pmu_disable(struct perf_event *event)
606{
607 struct drm_i915_private *i915 =
608 container_of(event->pmu, typeof(*i915), pmu.base);
609 unsigned int bit = event_enabled_bit(event);
610 unsigned long flags;
611
612 spin_lock_irqsave(&i915->pmu.lock, flags);
613
614 if (is_engine_event(event)) {
615 u8 sample = engine_event_sample(event);
616 struct intel_engine_cs *engine;
617
618 engine = intel_engine_lookup_user(i915,
619 engine_event_class(event),
620 engine_event_instance(event));
621 GEM_BUG_ON(!engine);
622 GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
623 GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
624 /*
625 * Decrement the reference count and clear the enabled
626 * bitmask when the last listener on an event goes away.
627 */
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000628 if (--engine->pmu.enable_count[sample] == 0)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000629 engine->pmu.enable &= ~BIT(sample);
630 }
631
632 GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
633 GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
634 /*
635 * Decrement the reference count and clear the enabled
636 * bitmask when the last listener on an event goes away.
637 */
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000638 if (--i915->pmu.enable_count[bit] == 0) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000639 i915->pmu.enable &= ~BIT_ULL(bit);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000640 i915->pmu.timer_enabled &= pmu_needs_timer(i915, true);
641 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000642
643 spin_unlock_irqrestore(&i915->pmu.lock, flags);
644}
645
646static void i915_pmu_event_start(struct perf_event *event, int flags)
647{
648 i915_pmu_enable(event);
649 event->hw.state = 0;
650}
651
652static void i915_pmu_event_stop(struct perf_event *event, int flags)
653{
654 if (flags & PERF_EF_UPDATE)
655 i915_pmu_event_read(event);
656 i915_pmu_disable(event);
657 event->hw.state = PERF_HES_STOPPED;
658}
659
660static int i915_pmu_event_add(struct perf_event *event, int flags)
661{
662 if (flags & PERF_EF_START)
663 i915_pmu_event_start(event, flags);
664
665 return 0;
666}
667
668static void i915_pmu_event_del(struct perf_event *event, int flags)
669{
670 i915_pmu_event_stop(event, PERF_EF_UPDATE);
671}
672
673static int i915_pmu_event_event_idx(struct perf_event *event)
674{
675 return 0;
676}
677
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000678struct i915_str_attribute {
679 struct device_attribute attr;
680 const char *str;
681};
682
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000683static ssize_t i915_pmu_format_show(struct device *dev,
684 struct device_attribute *attr, char *buf)
685{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000686 struct i915_str_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000687
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000688 eattr = container_of(attr, struct i915_str_attribute, attr);
689 return sprintf(buf, "%s\n", eattr->str);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000690}
691
692#define I915_PMU_FORMAT_ATTR(_name, _config) \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000693 (&((struct i915_str_attribute[]) { \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000694 { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000695 .str = _config, } \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000696 })[0].attr.attr)
697
698static struct attribute *i915_pmu_format_attrs[] = {
699 I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"),
700 NULL,
701};
702
703static const struct attribute_group i915_pmu_format_attr_group = {
704 .name = "format",
705 .attrs = i915_pmu_format_attrs,
706};
707
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000708struct i915_ext_attribute {
709 struct device_attribute attr;
710 unsigned long val;
711};
712
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000713static ssize_t i915_pmu_event_show(struct device *dev,
714 struct device_attribute *attr, char *buf)
715{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000716 struct i915_ext_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000717
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000718 eattr = container_of(attr, struct i915_ext_attribute, attr);
719 return sprintf(buf, "config=0x%lx\n", eattr->val);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000720}
721
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000722static struct attribute_group i915_pmu_events_attr_group = {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000723 .name = "events",
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000724 /* Patch in attrs at runtime. */
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000725};
726
727static ssize_t
728i915_pmu_get_attr_cpumask(struct device *dev,
729 struct device_attribute *attr,
730 char *buf)
731{
732 return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask);
733}
734
735static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL);
736
737static struct attribute *i915_cpumask_attrs[] = {
738 &dev_attr_cpumask.attr,
739 NULL,
740};
741
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000742static const struct attribute_group i915_pmu_cpumask_attr_group = {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000743 .attrs = i915_cpumask_attrs,
744};
745
746static const struct attribute_group *i915_pmu_attr_groups[] = {
747 &i915_pmu_format_attr_group,
748 &i915_pmu_events_attr_group,
749 &i915_pmu_cpumask_attr_group,
750 NULL
751};
752
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000753#define __event(__config, __name, __unit) \
754{ \
755 .config = (__config), \
756 .name = (__name), \
757 .unit = (__unit), \
758}
759
760#define __engine_event(__sample, __name) \
761{ \
762 .sample = (__sample), \
763 .name = (__name), \
764}
765
766static struct i915_ext_attribute *
767add_i915_attr(struct i915_ext_attribute *attr, const char *name, u64 config)
768{
Chris Wilson2bbba4e2018-01-11 14:04:02 +0000769 sysfs_attr_init(&attr->attr.attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000770 attr->attr.attr.name = name;
771 attr->attr.attr.mode = 0444;
772 attr->attr.show = i915_pmu_event_show;
773 attr->val = config;
774
775 return ++attr;
776}
777
778static struct perf_pmu_events_attr *
779add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,
780 const char *str)
781{
Chris Wilson2bbba4e2018-01-11 14:04:02 +0000782 sysfs_attr_init(&attr->attr.attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000783 attr->attr.attr.name = name;
784 attr->attr.attr.mode = 0444;
785 attr->attr.show = perf_event_sysfs_show;
786 attr->event_str = str;
787
788 return ++attr;
789}
790
791static struct attribute **
792create_event_attributes(struct drm_i915_private *i915)
793{
794 static const struct {
795 u64 config;
796 const char *name;
797 const char *unit;
798 } events[] = {
799 __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "MHz"),
800 __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "MHz"),
801 __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
802 __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
803 };
804 static const struct {
805 enum drm_i915_pmu_engine_sample sample;
806 char *name;
807 } engine_events[] = {
808 __engine_event(I915_SAMPLE_BUSY, "busy"),
809 __engine_event(I915_SAMPLE_SEMA, "sema"),
810 __engine_event(I915_SAMPLE_WAIT, "wait"),
811 };
812 unsigned int count = 0;
813 struct perf_pmu_events_attr *pmu_attr = NULL, *pmu_iter;
814 struct i915_ext_attribute *i915_attr = NULL, *i915_iter;
815 struct attribute **attr = NULL, **attr_iter;
816 struct intel_engine_cs *engine;
817 enum intel_engine_id id;
818 unsigned int i;
819
820 /* Count how many counters we will be exposing. */
821 for (i = 0; i < ARRAY_SIZE(events); i++) {
822 if (!config_status(i915, events[i].config))
823 count++;
824 }
825
826 for_each_engine(engine, i915, id) {
827 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
828 if (!engine_event_status(engine,
829 engine_events[i].sample))
830 count++;
831 }
832 }
833
834 /* Allocate attribute objects and table. */
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000835 i915_attr = kcalloc(count, sizeof(*i915_attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000836 if (!i915_attr)
837 goto err_alloc;
838
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000839 pmu_attr = kcalloc(count, sizeof(*pmu_attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000840 if (!pmu_attr)
841 goto err_alloc;
842
843 /* Max one pointer of each attribute type plus a termination entry. */
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000844 attr = kcalloc(count * 2 + 1, sizeof(*attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000845 if (!attr)
846 goto err_alloc;
847
848 i915_iter = i915_attr;
849 pmu_iter = pmu_attr;
850 attr_iter = attr;
851
852 /* Initialize supported non-engine counters. */
853 for (i = 0; i < ARRAY_SIZE(events); i++) {
854 char *str;
855
856 if (config_status(i915, events[i].config))
857 continue;
858
859 str = kstrdup(events[i].name, GFP_KERNEL);
860 if (!str)
861 goto err;
862
863 *attr_iter++ = &i915_iter->attr.attr;
864 i915_iter = add_i915_attr(i915_iter, str, events[i].config);
865
866 if (events[i].unit) {
867 str = kasprintf(GFP_KERNEL, "%s.unit", events[i].name);
868 if (!str)
869 goto err;
870
871 *attr_iter++ = &pmu_iter->attr.attr;
872 pmu_iter = add_pmu_attr(pmu_iter, str, events[i].unit);
873 }
874 }
875
876 /* Initialize supported engine counters. */
877 for_each_engine(engine, i915, id) {
878 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
879 char *str;
880
881 if (engine_event_status(engine,
882 engine_events[i].sample))
883 continue;
884
885 str = kasprintf(GFP_KERNEL, "%s-%s",
886 engine->name, engine_events[i].name);
887 if (!str)
888 goto err;
889
890 *attr_iter++ = &i915_iter->attr.attr;
891 i915_iter =
892 add_i915_attr(i915_iter, str,
Tvrtko Ursulin8810bc52018-01-23 13:45:58 +0000893 __I915_PMU_ENGINE(engine->uabi_class,
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000894 engine->instance,
895 engine_events[i].sample));
896
897 str = kasprintf(GFP_KERNEL, "%s-%s.unit",
898 engine->name, engine_events[i].name);
899 if (!str)
900 goto err;
901
902 *attr_iter++ = &pmu_iter->attr.attr;
903 pmu_iter = add_pmu_attr(pmu_iter, str, "ns");
904 }
905 }
906
907 i915->pmu.i915_attr = i915_attr;
908 i915->pmu.pmu_attr = pmu_attr;
909
910 return attr;
911
912err:;
913 for (attr_iter = attr; *attr_iter; attr_iter++)
914 kfree((*attr_iter)->name);
915
916err_alloc:
917 kfree(attr);
918 kfree(i915_attr);
919 kfree(pmu_attr);
920
921 return NULL;
922}
923
924static void free_event_attributes(struct drm_i915_private *i915)
925{
926 struct attribute **attr_iter = i915_pmu_events_attr_group.attrs;
927
928 for (; *attr_iter; attr_iter++)
929 kfree((*attr_iter)->name);
930
931 kfree(i915_pmu_events_attr_group.attrs);
932 kfree(i915->pmu.i915_attr);
933 kfree(i915->pmu.pmu_attr);
934
935 i915_pmu_events_attr_group.attrs = NULL;
936 i915->pmu.i915_attr = NULL;
937 i915->pmu.pmu_attr = NULL;
938}
939
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000940static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
941{
942 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000943
944 GEM_BUG_ON(!pmu->base.event_init);
945
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000946 /* Select the first online CPU as a designated reader. */
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000947 if (!cpumask_weight(&i915_pmu_cpumask))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000948 cpumask_set_cpu(cpu, &i915_pmu_cpumask);
949
950 return 0;
951}
952
953static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
954{
955 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
956 unsigned int target;
957
958 GEM_BUG_ON(!pmu->base.event_init);
959
960 if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) {
961 target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
962 /* Migrate events if there is a valid target */
963 if (target < nr_cpu_ids) {
964 cpumask_set_cpu(target, &i915_pmu_cpumask);
965 perf_pmu_migrate_context(&pmu->base, cpu, target);
966 }
967 }
968
969 return 0;
970}
971
972static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000973
974static int i915_pmu_register_cpuhp_state(struct drm_i915_private *i915)
975{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000976 enum cpuhp_state slot;
977 int ret;
978
979 ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
980 "perf/x86/intel/i915:online",
981 i915_pmu_cpu_online,
982 i915_pmu_cpu_offline);
983 if (ret < 0)
984 return ret;
985
986 slot = ret;
987 ret = cpuhp_state_add_instance(slot, &i915->pmu.node);
988 if (ret) {
989 cpuhp_remove_multi_state(slot);
990 return ret;
991 }
992
993 cpuhp_slot = slot;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000994 return 0;
995}
996
997static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915)
998{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000999 WARN_ON(cpuhp_slot == CPUHP_INVALID);
1000 WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &i915->pmu.node));
1001 cpuhp_remove_multi_state(cpuhp_slot);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001002}
1003
1004void i915_pmu_register(struct drm_i915_private *i915)
1005{
1006 int ret;
1007
1008 if (INTEL_GEN(i915) <= 2) {
1009 DRM_INFO("PMU not supported for this GPU.");
1010 return;
1011 }
1012
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001013 i915_pmu_events_attr_group.attrs = create_event_attributes(i915);
1014 if (!i915_pmu_events_attr_group.attrs) {
1015 ret = -ENOMEM;
1016 goto err;
1017 }
1018
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001019 i915->pmu.base.attr_groups = i915_pmu_attr_groups;
1020 i915->pmu.base.task_ctx_nr = perf_invalid_context;
1021 i915->pmu.base.event_init = i915_pmu_event_init;
1022 i915->pmu.base.add = i915_pmu_event_add;
1023 i915->pmu.base.del = i915_pmu_event_del;
1024 i915->pmu.base.start = i915_pmu_event_start;
1025 i915->pmu.base.stop = i915_pmu_event_stop;
1026 i915->pmu.base.read = i915_pmu_event_read;
1027 i915->pmu.base.event_idx = i915_pmu_event_event_idx;
1028
1029 spin_lock_init(&i915->pmu.lock);
1030 hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1031 i915->pmu.timer.function = i915_sample;
1032
1033 ret = perf_pmu_register(&i915->pmu.base, "i915", -1);
1034 if (ret)
1035 goto err;
1036
1037 ret = i915_pmu_register_cpuhp_state(i915);
1038 if (ret)
1039 goto err_unreg;
1040
1041 return;
1042
1043err_unreg:
1044 perf_pmu_unregister(&i915->pmu.base);
1045err:
1046 i915->pmu.base.event_init = NULL;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001047 free_event_attributes(i915);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001048 DRM_NOTE("Failed to register PMU! (err=%d)\n", ret);
1049}
1050
1051void i915_pmu_unregister(struct drm_i915_private *i915)
1052{
1053 if (!i915->pmu.base.event_init)
1054 return;
1055
1056 WARN_ON(i915->pmu.enable);
1057
1058 hrtimer_cancel(&i915->pmu.timer);
1059
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001060 i915_pmu_unregister_cpuhp_state(i915);
1061
1062 perf_pmu_unregister(&i915->pmu.base);
1063 i915->pmu.base.event_init = NULL;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001064 free_event_attributes(i915);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001065}