blob: 1c440460255ddcd0ff3916107b705fc881d254d6 [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
418static u64 __i915_pmu_event_read(struct perf_event *event)
419{
420 struct drm_i915_private *i915 =
421 container_of(event->pmu, typeof(*i915), pmu.base);
422 u64 val = 0;
423
424 if (is_engine_event(event)) {
425 u8 sample = engine_event_sample(event);
426 struct intel_engine_cs *engine;
427
428 engine = intel_engine_lookup_user(i915,
429 engine_event_class(event),
430 engine_event_instance(event));
431
432 if (WARN_ON_ONCE(!engine)) {
433 /* Do nothing */
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000434 } else if (sample == I915_SAMPLE_BUSY &&
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000435 intel_engine_supports_stats(engine)) {
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000436 val = ktime_to_ns(intel_engine_get_busy_time(engine));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000437 } else {
438 val = engine->pmu.sample[sample].cur;
439 }
440 } else {
441 switch (event->attr.config) {
442 case I915_PMU_ACTUAL_FREQUENCY:
443 val =
444 div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_ACT].cur,
445 FREQUENCY);
446 break;
447 case I915_PMU_REQUESTED_FREQUENCY:
448 val =
449 div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_REQ].cur,
450 FREQUENCY);
451 break;
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000452 case I915_PMU_INTERRUPTS:
453 val = count_interrupts(i915);
454 break;
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000455 case I915_PMU_RC6_RESIDENCY:
456 intel_runtime_pm_get(i915);
457 val = intel_rc6_residency_ns(i915,
458 IS_VALLEYVIEW(i915) ?
459 VLV_GT_RENDER_RC6 :
460 GEN6_GT_GFX_RC6);
Chris Wilsonfb6db0f2017-12-01 11:30:30 +0000461 if (HAS_RC6p(i915))
Tvrtko Ursulin3452fa32017-11-24 17:13:31 +0000462 val += intel_rc6_residency_ns(i915,
463 GEN6_GT_GFX_RC6p);
Chris Wilsonfb6db0f2017-12-01 11:30:30 +0000464 if (HAS_RC6pp(i915))
Tvrtko Ursulin3452fa32017-11-24 17:13:31 +0000465 val += intel_rc6_residency_ns(i915,
466 GEN6_GT_GFX_RC6pp);
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000467 intel_runtime_pm_put(i915);
468 break;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000469 }
470 }
471
472 return val;
473}
474
475static void i915_pmu_event_read(struct perf_event *event)
476{
477 struct hw_perf_event *hwc = &event->hw;
478 u64 prev, new;
479
480again:
481 prev = local64_read(&hwc->prev_count);
482 new = __i915_pmu_event_read(event);
483
484 if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
485 goto again;
486
487 local64_add(new - prev, &event->count);
488}
489
490static void i915_pmu_enable(struct perf_event *event)
491{
492 struct drm_i915_private *i915 =
493 container_of(event->pmu, typeof(*i915), pmu.base);
494 unsigned int bit = event_enabled_bit(event);
495 unsigned long flags;
496
497 spin_lock_irqsave(&i915->pmu.lock, flags);
498
499 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000500 * Update the bitmask of enabled events and increment
501 * the event reference counter.
502 */
503 GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
504 GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
505 i915->pmu.enable |= BIT_ULL(bit);
506 i915->pmu.enable_count[bit]++;
507
508 /*
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000509 * Start the sampling timer if needed and not already enabled.
510 */
511 __i915_pmu_maybe_start_timer(i915);
512
513 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000514 * For per-engine events the bitmask and reference counting
515 * is stored per engine.
516 */
517 if (is_engine_event(event)) {
518 u8 sample = engine_event_sample(event);
519 struct intel_engine_cs *engine;
520
521 engine = intel_engine_lookup_user(i915,
522 engine_event_class(event),
523 engine_event_instance(event));
524 GEM_BUG_ON(!engine);
525 engine->pmu.enable |= BIT(sample);
526
527 GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
528 GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000529 engine->pmu.enable_count[sample]++;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000530 }
531
532 /*
533 * Store the current counter value so we can report the correct delta
534 * for all listeners. Even when the event was already enabled and has
535 * an existing non-zero value.
536 */
537 local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
538
539 spin_unlock_irqrestore(&i915->pmu.lock, flags);
540}
541
542static void i915_pmu_disable(struct perf_event *event)
543{
544 struct drm_i915_private *i915 =
545 container_of(event->pmu, typeof(*i915), pmu.base);
546 unsigned int bit = event_enabled_bit(event);
547 unsigned long flags;
548
549 spin_lock_irqsave(&i915->pmu.lock, flags);
550
551 if (is_engine_event(event)) {
552 u8 sample = engine_event_sample(event);
553 struct intel_engine_cs *engine;
554
555 engine = intel_engine_lookup_user(i915,
556 engine_event_class(event),
557 engine_event_instance(event));
558 GEM_BUG_ON(!engine);
559 GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
560 GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
561 /*
562 * Decrement the reference count and clear the enabled
563 * bitmask when the last listener on an event goes away.
564 */
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000565 if (--engine->pmu.enable_count[sample] == 0)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000566 engine->pmu.enable &= ~BIT(sample);
567 }
568
569 GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
570 GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
571 /*
572 * Decrement the reference count and clear the enabled
573 * bitmask when the last listener on an event goes away.
574 */
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000575 if (--i915->pmu.enable_count[bit] == 0) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000576 i915->pmu.enable &= ~BIT_ULL(bit);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000577 i915->pmu.timer_enabled &= pmu_needs_timer(i915, true);
578 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000579
580 spin_unlock_irqrestore(&i915->pmu.lock, flags);
581}
582
583static void i915_pmu_event_start(struct perf_event *event, int flags)
584{
585 i915_pmu_enable(event);
586 event->hw.state = 0;
587}
588
589static void i915_pmu_event_stop(struct perf_event *event, int flags)
590{
591 if (flags & PERF_EF_UPDATE)
592 i915_pmu_event_read(event);
593 i915_pmu_disable(event);
594 event->hw.state = PERF_HES_STOPPED;
595}
596
597static int i915_pmu_event_add(struct perf_event *event, int flags)
598{
599 if (flags & PERF_EF_START)
600 i915_pmu_event_start(event, flags);
601
602 return 0;
603}
604
605static void i915_pmu_event_del(struct perf_event *event, int flags)
606{
607 i915_pmu_event_stop(event, PERF_EF_UPDATE);
608}
609
610static int i915_pmu_event_event_idx(struct perf_event *event)
611{
612 return 0;
613}
614
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000615struct i915_str_attribute {
616 struct device_attribute attr;
617 const char *str;
618};
619
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000620static ssize_t i915_pmu_format_show(struct device *dev,
621 struct device_attribute *attr, char *buf)
622{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000623 struct i915_str_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000624
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000625 eattr = container_of(attr, struct i915_str_attribute, attr);
626 return sprintf(buf, "%s\n", eattr->str);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000627}
628
629#define I915_PMU_FORMAT_ATTR(_name, _config) \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000630 (&((struct i915_str_attribute[]) { \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000631 { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000632 .str = _config, } \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000633 })[0].attr.attr)
634
635static struct attribute *i915_pmu_format_attrs[] = {
636 I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"),
637 NULL,
638};
639
640static const struct attribute_group i915_pmu_format_attr_group = {
641 .name = "format",
642 .attrs = i915_pmu_format_attrs,
643};
644
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000645struct i915_ext_attribute {
646 struct device_attribute attr;
647 unsigned long val;
648};
649
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000650static ssize_t i915_pmu_event_show(struct device *dev,
651 struct device_attribute *attr, char *buf)
652{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000653 struct i915_ext_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000654
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000655 eattr = container_of(attr, struct i915_ext_attribute, attr);
656 return sprintf(buf, "config=0x%lx\n", eattr->val);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000657}
658
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000659static struct attribute_group i915_pmu_events_attr_group = {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000660 .name = "events",
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000661 /* Patch in attrs at runtime. */
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000662};
663
664static ssize_t
665i915_pmu_get_attr_cpumask(struct device *dev,
666 struct device_attribute *attr,
667 char *buf)
668{
669 return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask);
670}
671
672static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL);
673
674static struct attribute *i915_cpumask_attrs[] = {
675 &dev_attr_cpumask.attr,
676 NULL,
677};
678
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000679static const struct attribute_group i915_pmu_cpumask_attr_group = {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000680 .attrs = i915_cpumask_attrs,
681};
682
683static const struct attribute_group *i915_pmu_attr_groups[] = {
684 &i915_pmu_format_attr_group,
685 &i915_pmu_events_attr_group,
686 &i915_pmu_cpumask_attr_group,
687 NULL
688};
689
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000690#define __event(__config, __name, __unit) \
691{ \
692 .config = (__config), \
693 .name = (__name), \
694 .unit = (__unit), \
695}
696
697#define __engine_event(__sample, __name) \
698{ \
699 .sample = (__sample), \
700 .name = (__name), \
701}
702
703static struct i915_ext_attribute *
704add_i915_attr(struct i915_ext_attribute *attr, const char *name, u64 config)
705{
Chris Wilson2bbba4e2018-01-11 14:04:02 +0000706 sysfs_attr_init(&attr->attr.attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000707 attr->attr.attr.name = name;
708 attr->attr.attr.mode = 0444;
709 attr->attr.show = i915_pmu_event_show;
710 attr->val = config;
711
712 return ++attr;
713}
714
715static struct perf_pmu_events_attr *
716add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,
717 const char *str)
718{
Chris Wilson2bbba4e2018-01-11 14:04:02 +0000719 sysfs_attr_init(&attr->attr.attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000720 attr->attr.attr.name = name;
721 attr->attr.attr.mode = 0444;
722 attr->attr.show = perf_event_sysfs_show;
723 attr->event_str = str;
724
725 return ++attr;
726}
727
728static struct attribute **
729create_event_attributes(struct drm_i915_private *i915)
730{
731 static const struct {
732 u64 config;
733 const char *name;
734 const char *unit;
735 } events[] = {
736 __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "MHz"),
737 __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "MHz"),
738 __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
739 __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
740 };
741 static const struct {
742 enum drm_i915_pmu_engine_sample sample;
743 char *name;
744 } engine_events[] = {
745 __engine_event(I915_SAMPLE_BUSY, "busy"),
746 __engine_event(I915_SAMPLE_SEMA, "sema"),
747 __engine_event(I915_SAMPLE_WAIT, "wait"),
748 };
749 unsigned int count = 0;
750 struct perf_pmu_events_attr *pmu_attr = NULL, *pmu_iter;
751 struct i915_ext_attribute *i915_attr = NULL, *i915_iter;
752 struct attribute **attr = NULL, **attr_iter;
753 struct intel_engine_cs *engine;
754 enum intel_engine_id id;
755 unsigned int i;
756
757 /* Count how many counters we will be exposing. */
758 for (i = 0; i < ARRAY_SIZE(events); i++) {
759 if (!config_status(i915, events[i].config))
760 count++;
761 }
762
763 for_each_engine(engine, i915, id) {
764 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
765 if (!engine_event_status(engine,
766 engine_events[i].sample))
767 count++;
768 }
769 }
770
771 /* Allocate attribute objects and table. */
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000772 i915_attr = kcalloc(count, sizeof(*i915_attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000773 if (!i915_attr)
774 goto err_alloc;
775
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000776 pmu_attr = kcalloc(count, sizeof(*pmu_attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000777 if (!pmu_attr)
778 goto err_alloc;
779
780 /* Max one pointer of each attribute type plus a termination entry. */
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000781 attr = kcalloc(count * 2 + 1, sizeof(*attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000782 if (!attr)
783 goto err_alloc;
784
785 i915_iter = i915_attr;
786 pmu_iter = pmu_attr;
787 attr_iter = attr;
788
789 /* Initialize supported non-engine counters. */
790 for (i = 0; i < ARRAY_SIZE(events); i++) {
791 char *str;
792
793 if (config_status(i915, events[i].config))
794 continue;
795
796 str = kstrdup(events[i].name, GFP_KERNEL);
797 if (!str)
798 goto err;
799
800 *attr_iter++ = &i915_iter->attr.attr;
801 i915_iter = add_i915_attr(i915_iter, str, events[i].config);
802
803 if (events[i].unit) {
804 str = kasprintf(GFP_KERNEL, "%s.unit", events[i].name);
805 if (!str)
806 goto err;
807
808 *attr_iter++ = &pmu_iter->attr.attr;
809 pmu_iter = add_pmu_attr(pmu_iter, str, events[i].unit);
810 }
811 }
812
813 /* Initialize supported engine counters. */
814 for_each_engine(engine, i915, id) {
815 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
816 char *str;
817
818 if (engine_event_status(engine,
819 engine_events[i].sample))
820 continue;
821
822 str = kasprintf(GFP_KERNEL, "%s-%s",
823 engine->name, engine_events[i].name);
824 if (!str)
825 goto err;
826
827 *attr_iter++ = &i915_iter->attr.attr;
828 i915_iter =
829 add_i915_attr(i915_iter, str,
Tvrtko Ursulin8810bc52018-01-23 13:45:58 +0000830 __I915_PMU_ENGINE(engine->uabi_class,
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000831 engine->instance,
832 engine_events[i].sample));
833
834 str = kasprintf(GFP_KERNEL, "%s-%s.unit",
835 engine->name, engine_events[i].name);
836 if (!str)
837 goto err;
838
839 *attr_iter++ = &pmu_iter->attr.attr;
840 pmu_iter = add_pmu_attr(pmu_iter, str, "ns");
841 }
842 }
843
844 i915->pmu.i915_attr = i915_attr;
845 i915->pmu.pmu_attr = pmu_attr;
846
847 return attr;
848
849err:;
850 for (attr_iter = attr; *attr_iter; attr_iter++)
851 kfree((*attr_iter)->name);
852
853err_alloc:
854 kfree(attr);
855 kfree(i915_attr);
856 kfree(pmu_attr);
857
858 return NULL;
859}
860
861static void free_event_attributes(struct drm_i915_private *i915)
862{
863 struct attribute **attr_iter = i915_pmu_events_attr_group.attrs;
864
865 for (; *attr_iter; attr_iter++)
866 kfree((*attr_iter)->name);
867
868 kfree(i915_pmu_events_attr_group.attrs);
869 kfree(i915->pmu.i915_attr);
870 kfree(i915->pmu.pmu_attr);
871
872 i915_pmu_events_attr_group.attrs = NULL;
873 i915->pmu.i915_attr = NULL;
874 i915->pmu.pmu_attr = NULL;
875}
876
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000877static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
878{
879 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000880
881 GEM_BUG_ON(!pmu->base.event_init);
882
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000883 /* Select the first online CPU as a designated reader. */
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000884 if (!cpumask_weight(&i915_pmu_cpumask))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000885 cpumask_set_cpu(cpu, &i915_pmu_cpumask);
886
887 return 0;
888}
889
890static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
891{
892 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
893 unsigned int target;
894
895 GEM_BUG_ON(!pmu->base.event_init);
896
897 if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) {
898 target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
899 /* Migrate events if there is a valid target */
900 if (target < nr_cpu_ids) {
901 cpumask_set_cpu(target, &i915_pmu_cpumask);
902 perf_pmu_migrate_context(&pmu->base, cpu, target);
903 }
904 }
905
906 return 0;
907}
908
909static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000910
911static int i915_pmu_register_cpuhp_state(struct drm_i915_private *i915)
912{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000913 enum cpuhp_state slot;
914 int ret;
915
916 ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
917 "perf/x86/intel/i915:online",
918 i915_pmu_cpu_online,
919 i915_pmu_cpu_offline);
920 if (ret < 0)
921 return ret;
922
923 slot = ret;
924 ret = cpuhp_state_add_instance(slot, &i915->pmu.node);
925 if (ret) {
926 cpuhp_remove_multi_state(slot);
927 return ret;
928 }
929
930 cpuhp_slot = slot;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000931 return 0;
932}
933
934static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915)
935{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000936 WARN_ON(cpuhp_slot == CPUHP_INVALID);
937 WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &i915->pmu.node));
938 cpuhp_remove_multi_state(cpuhp_slot);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000939}
940
941void i915_pmu_register(struct drm_i915_private *i915)
942{
943 int ret;
944
945 if (INTEL_GEN(i915) <= 2) {
946 DRM_INFO("PMU not supported for this GPU.");
947 return;
948 }
949
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000950 i915_pmu_events_attr_group.attrs = create_event_attributes(i915);
951 if (!i915_pmu_events_attr_group.attrs) {
952 ret = -ENOMEM;
953 goto err;
954 }
955
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000956 i915->pmu.base.attr_groups = i915_pmu_attr_groups;
957 i915->pmu.base.task_ctx_nr = perf_invalid_context;
958 i915->pmu.base.event_init = i915_pmu_event_init;
959 i915->pmu.base.add = i915_pmu_event_add;
960 i915->pmu.base.del = i915_pmu_event_del;
961 i915->pmu.base.start = i915_pmu_event_start;
962 i915->pmu.base.stop = i915_pmu_event_stop;
963 i915->pmu.base.read = i915_pmu_event_read;
964 i915->pmu.base.event_idx = i915_pmu_event_event_idx;
965
966 spin_lock_init(&i915->pmu.lock);
967 hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
968 i915->pmu.timer.function = i915_sample;
969
970 ret = perf_pmu_register(&i915->pmu.base, "i915", -1);
971 if (ret)
972 goto err;
973
974 ret = i915_pmu_register_cpuhp_state(i915);
975 if (ret)
976 goto err_unreg;
977
978 return;
979
980err_unreg:
981 perf_pmu_unregister(&i915->pmu.base);
982err:
983 i915->pmu.base.event_init = NULL;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000984 free_event_attributes(i915);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000985 DRM_NOTE("Failed to register PMU! (err=%d)\n", ret);
986}
987
988void i915_pmu_unregister(struct drm_i915_private *i915)
989{
990 if (!i915->pmu.base.event_init)
991 return;
992
993 WARN_ON(i915->pmu.enable);
994
995 hrtimer_cancel(&i915->pmu.timer);
996
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000997 i915_pmu_unregister_cpuhp_state(i915);
998
999 perf_pmu_unregister(&i915->pmu.base);
1000 i915->pmu.base.event_init = NULL;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001001 free_event_attributes(i915);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001002}