blob: 1c0ee9d68b0460acf73cd8b69864e0d15aac0f0a [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 Ursulinb3add012017-11-21 18:18:49 +000093static bool supports_busy_stats(struct drm_i915_private *i915)
94{
95 return INTEL_GEN(i915) >= 8;
96}
97
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +000098static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
99{
100 u64 enable;
101
102 /*
103 * Only some counters need the sampling timer.
104 *
105 * We start with a bitmask of all currently enabled events.
106 */
107 enable = i915->pmu.enable;
108
109 /*
110 * Mask out all the ones which do not need the timer, or in
111 * other words keep all the ones that could need the timer.
112 */
113 enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
114 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
115 ENGINE_SAMPLE_MASK;
116
117 /*
118 * When the GPU is idle per-engine counters do not need to be
119 * running so clear those bits out.
120 */
121 if (!gpu_active)
122 enable &= ~ENGINE_SAMPLE_MASK;
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000123 /*
124 * Also there is software busyness tracking available we do not
125 * need the timer for I915_SAMPLE_BUSY counter.
126 */
127 else if (supports_busy_stats(i915))
128 enable &= ~BIT(I915_SAMPLE_BUSY);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000129
130 /*
131 * If some bits remain it means we need the sampling timer running.
132 */
133 return enable;
134}
135
136void i915_pmu_gt_parked(struct drm_i915_private *i915)
137{
138 if (!i915->pmu.base.event_init)
139 return;
140
141 spin_lock_irq(&i915->pmu.lock);
142 /*
143 * Signal sampling timer to stop if only engine events are enabled and
144 * GPU went idle.
145 */
146 i915->pmu.timer_enabled = pmu_needs_timer(i915, false);
147 spin_unlock_irq(&i915->pmu.lock);
148}
149
150static void __i915_pmu_maybe_start_timer(struct drm_i915_private *i915)
151{
152 if (!i915->pmu.timer_enabled && pmu_needs_timer(i915, true)) {
153 i915->pmu.timer_enabled = true;
154 hrtimer_start_range_ns(&i915->pmu.timer,
155 ns_to_ktime(PERIOD), 0,
156 HRTIMER_MODE_REL_PINNED);
157 }
158}
159
160void i915_pmu_gt_unparked(struct drm_i915_private *i915)
161{
162 if (!i915->pmu.base.event_init)
163 return;
164
165 spin_lock_irq(&i915->pmu.lock);
166 /*
167 * Re-enable sampling timer when GPU goes active.
168 */
169 __i915_pmu_maybe_start_timer(i915);
170 spin_unlock_irq(&i915->pmu.lock);
171}
172
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000173static bool grab_forcewake(struct drm_i915_private *i915, bool fw)
174{
175 if (!fw)
176 intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
177
178 return true;
179}
180
181static void
182update_sample(struct i915_pmu_sample *sample, u32 unit, u32 val)
183{
Tvrtko Ursulin8ee4f192017-11-24 09:49:59 +0000184 sample->cur += mul_u32_u32(val, unit);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000185}
186
187static void engines_sample(struct drm_i915_private *dev_priv)
188{
189 struct intel_engine_cs *engine;
190 enum intel_engine_id id;
191 bool fw = false;
192
193 if ((dev_priv->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
194 return;
195
196 if (!dev_priv->gt.awake)
197 return;
198
199 if (!intel_runtime_pm_get_if_in_use(dev_priv))
200 return;
201
202 for_each_engine(engine, dev_priv, id) {
203 u32 current_seqno = intel_engine_get_seqno(engine);
204 u32 last_seqno = intel_engine_last_submit(engine);
205 u32 val;
206
207 val = !i915_seqno_passed(current_seqno, last_seqno);
208
209 update_sample(&engine->pmu.sample[I915_SAMPLE_BUSY],
210 PERIOD, val);
211
212 if (val && (engine->pmu.enable &
213 (BIT(I915_SAMPLE_WAIT) | BIT(I915_SAMPLE_SEMA)))) {
214 fw = grab_forcewake(dev_priv, fw);
215
216 val = I915_READ_FW(RING_CTL(engine->mmio_base));
217 } else {
218 val = 0;
219 }
220
221 update_sample(&engine->pmu.sample[I915_SAMPLE_WAIT],
222 PERIOD, !!(val & RING_WAIT));
223
224 update_sample(&engine->pmu.sample[I915_SAMPLE_SEMA],
225 PERIOD, !!(val & RING_WAIT_SEMAPHORE));
226 }
227
228 if (fw)
229 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
230
231 intel_runtime_pm_put(dev_priv);
232}
233
234static void frequency_sample(struct drm_i915_private *dev_priv)
235{
236 if (dev_priv->pmu.enable &
237 config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
238 u32 val;
239
240 val = dev_priv->gt_pm.rps.cur_freq;
241 if (dev_priv->gt.awake &&
242 intel_runtime_pm_get_if_in_use(dev_priv)) {
243 val = intel_get_cagf(dev_priv,
244 I915_READ_NOTRACE(GEN6_RPSTAT1));
245 intel_runtime_pm_put(dev_priv);
246 }
247
248 update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
249 1, intel_gpu_freq(dev_priv, val));
250 }
251
252 if (dev_priv->pmu.enable &
253 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
254 update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_REQ], 1,
255 intel_gpu_freq(dev_priv,
256 dev_priv->gt_pm.rps.cur_freq));
257 }
258}
259
260static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
261{
262 struct drm_i915_private *i915 =
263 container_of(hrtimer, struct drm_i915_private, pmu.timer);
264
Tvrtko Ursulin8ee4f192017-11-24 09:49:59 +0000265 if (!READ_ONCE(i915->pmu.timer_enabled))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000266 return HRTIMER_NORESTART;
267
268 engines_sample(i915);
269 frequency_sample(i915);
270
271 hrtimer_forward_now(hrtimer, ns_to_ktime(PERIOD));
272 return HRTIMER_RESTART;
273}
274
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000275static u64 count_interrupts(struct drm_i915_private *i915)
276{
277 /* open-coded kstat_irqs() */
278 struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq);
279 u64 sum = 0;
280 int cpu;
281
282 if (!desc || !desc->kstat_irqs)
283 return 0;
284
285 for_each_possible_cpu(cpu)
286 sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
287
288 return sum;
289}
290
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000291static void i915_pmu_event_destroy(struct perf_event *event)
292{
293 WARN_ON(event->parent);
294}
295
296static int engine_event_init(struct perf_event *event)
297{
298 struct drm_i915_private *i915 =
299 container_of(event->pmu, typeof(*i915), pmu.base);
300
301 if (!intel_engine_lookup_user(i915, engine_event_class(event),
302 engine_event_instance(event)))
303 return -ENODEV;
304
305 switch (engine_event_sample(event)) {
306 case I915_SAMPLE_BUSY:
307 case I915_SAMPLE_WAIT:
308 break;
309 case I915_SAMPLE_SEMA:
310 if (INTEL_GEN(i915) < 6)
311 return -ENODEV;
312 break;
313 default:
314 return -ENOENT;
315 }
316
317 return 0;
318}
319
320static int i915_pmu_event_init(struct perf_event *event)
321{
322 struct drm_i915_private *i915 =
323 container_of(event->pmu, typeof(*i915), pmu.base);
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000324 int ret;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000325
326 if (event->attr.type != event->pmu->type)
327 return -ENOENT;
328
329 /* unsupported modes and filters */
330 if (event->attr.sample_period) /* no sampling */
331 return -EINVAL;
332
333 if (has_branch_stack(event))
334 return -EOPNOTSUPP;
335
336 if (event->cpu < 0)
337 return -EINVAL;
338
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000339 /* only allow running on one cpu at a time */
340 if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask))
Tvrtko Ursulin00a79722017-11-28 10:55:15 +0000341 return -EINVAL;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000342
343 if (is_engine_event(event)) {
344 ret = engine_event_init(event);
345 } else {
346 ret = 0;
347 switch (event->attr.config) {
348 case I915_PMU_ACTUAL_FREQUENCY:
349 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
350 /* Requires a mutex for sampling! */
351 ret = -ENODEV;
352 case I915_PMU_REQUESTED_FREQUENCY:
353 if (INTEL_GEN(i915) < 6)
354 ret = -ENODEV;
355 break;
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000356 case I915_PMU_INTERRUPTS:
357 break;
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000358 case I915_PMU_RC6_RESIDENCY:
359 if (!HAS_RC6(i915))
360 ret = -ENODEV;
361 break;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000362 default:
363 ret = -ENOENT;
364 break;
365 }
366 }
367 if (ret)
368 return ret;
369
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000370 if (!event->parent)
371 event->destroy = i915_pmu_event_destroy;
372
373 return 0;
374}
375
376static u64 __i915_pmu_event_read(struct perf_event *event)
377{
378 struct drm_i915_private *i915 =
379 container_of(event->pmu, typeof(*i915), pmu.base);
380 u64 val = 0;
381
382 if (is_engine_event(event)) {
383 u8 sample = engine_event_sample(event);
384 struct intel_engine_cs *engine;
385
386 engine = intel_engine_lookup_user(i915,
387 engine_event_class(event),
388 engine_event_instance(event));
389
390 if (WARN_ON_ONCE(!engine)) {
391 /* Do nothing */
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000392 } else if (sample == I915_SAMPLE_BUSY &&
393 engine->pmu.busy_stats) {
394 val = ktime_to_ns(intel_engine_get_busy_time(engine));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000395 } else {
396 val = engine->pmu.sample[sample].cur;
397 }
398 } else {
399 switch (event->attr.config) {
400 case I915_PMU_ACTUAL_FREQUENCY:
401 val =
402 div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_ACT].cur,
403 FREQUENCY);
404 break;
405 case I915_PMU_REQUESTED_FREQUENCY:
406 val =
407 div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_REQ].cur,
408 FREQUENCY);
409 break;
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000410 case I915_PMU_INTERRUPTS:
411 val = count_interrupts(i915);
412 break;
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000413 case I915_PMU_RC6_RESIDENCY:
414 intel_runtime_pm_get(i915);
415 val = intel_rc6_residency_ns(i915,
416 IS_VALLEYVIEW(i915) ?
417 VLV_GT_RENDER_RC6 :
418 GEN6_GT_GFX_RC6);
Tvrtko Ursulin3452fa32017-11-24 17:13:31 +0000419 if (HAS_RC6p(i915)) {
420 val += intel_rc6_residency_ns(i915,
421 GEN6_GT_GFX_RC6p);
422 val += intel_rc6_residency_ns(i915,
423 GEN6_GT_GFX_RC6pp);
424 }
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000425 intel_runtime_pm_put(i915);
426 break;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000427 }
428 }
429
430 return val;
431}
432
433static void i915_pmu_event_read(struct perf_event *event)
434{
435 struct hw_perf_event *hwc = &event->hw;
436 u64 prev, new;
437
438again:
439 prev = local64_read(&hwc->prev_count);
440 new = __i915_pmu_event_read(event);
441
442 if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
443 goto again;
444
445 local64_add(new - prev, &event->count);
446}
447
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000448static bool engine_needs_busy_stats(struct intel_engine_cs *engine)
449{
450 return supports_busy_stats(engine->i915) &&
451 (engine->pmu.enable & BIT(I915_SAMPLE_BUSY));
452}
453
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000454static void i915_pmu_enable(struct perf_event *event)
455{
456 struct drm_i915_private *i915 =
457 container_of(event->pmu, typeof(*i915), pmu.base);
458 unsigned int bit = event_enabled_bit(event);
459 unsigned long flags;
460
461 spin_lock_irqsave(&i915->pmu.lock, flags);
462
463 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000464 * Update the bitmask of enabled events and increment
465 * the event reference counter.
466 */
467 GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
468 GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
469 i915->pmu.enable |= BIT_ULL(bit);
470 i915->pmu.enable_count[bit]++;
471
472 /*
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000473 * Start the sampling timer if needed and not already enabled.
474 */
475 __i915_pmu_maybe_start_timer(i915);
476
477 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000478 * For per-engine events the bitmask and reference counting
479 * is stored per engine.
480 */
481 if (is_engine_event(event)) {
482 u8 sample = engine_event_sample(event);
483 struct intel_engine_cs *engine;
484
485 engine = intel_engine_lookup_user(i915,
486 engine_event_class(event),
487 engine_event_instance(event));
488 GEM_BUG_ON(!engine);
489 engine->pmu.enable |= BIT(sample);
490
491 GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
492 GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000493 if (engine->pmu.enable_count[sample]++ == 0) {
494 /*
495 * Enable engine busy stats tracking if needed or
496 * alternatively cancel the scheduled disable.
497 *
498 * If the delayed disable was pending, cancel it and
499 * in this case do not enable since it already is.
500 */
501 if (engine_needs_busy_stats(engine) &&
502 !engine->pmu.busy_stats) {
503 engine->pmu.busy_stats = true;
504 if (!cancel_delayed_work(&engine->pmu.disable_busy_stats))
505 intel_enable_engine_stats(engine);
506 }
507 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000508 }
509
510 /*
511 * Store the current counter value so we can report the correct delta
512 * for all listeners. Even when the event was already enabled and has
513 * an existing non-zero value.
514 */
515 local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
516
517 spin_unlock_irqrestore(&i915->pmu.lock, flags);
518}
519
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000520static void __disable_busy_stats(struct work_struct *work)
521{
522 struct intel_engine_cs *engine =
523 container_of(work, typeof(*engine), pmu.disable_busy_stats.work);
524
525 intel_disable_engine_stats(engine);
526}
527
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000528static void i915_pmu_disable(struct perf_event *event)
529{
530 struct drm_i915_private *i915 =
531 container_of(event->pmu, typeof(*i915), pmu.base);
532 unsigned int bit = event_enabled_bit(event);
533 unsigned long flags;
534
535 spin_lock_irqsave(&i915->pmu.lock, flags);
536
537 if (is_engine_event(event)) {
538 u8 sample = engine_event_sample(event);
539 struct intel_engine_cs *engine;
540
541 engine = intel_engine_lookup_user(i915,
542 engine_event_class(event),
543 engine_event_instance(event));
544 GEM_BUG_ON(!engine);
545 GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
546 GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
547 /*
548 * Decrement the reference count and clear the enabled
549 * bitmask when the last listener on an event goes away.
550 */
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000551 if (--engine->pmu.enable_count[sample] == 0) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000552 engine->pmu.enable &= ~BIT(sample);
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000553 if (!engine_needs_busy_stats(engine) &&
554 engine->pmu.busy_stats) {
555 engine->pmu.busy_stats = false;
556 /*
557 * We request a delayed disable to handle the
558 * rapid on/off cycles on events, which can
559 * happen when tools like perf stat start, in a
560 * nicer way.
561 *
562 * In addition, this also helps with busy stats
563 * accuracy with background CPU offline/online
564 * migration events.
565 */
566 queue_delayed_work(system_wq,
567 &engine->pmu.disable_busy_stats,
568 round_jiffies_up_relative(HZ));
569 }
570 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000571 }
572
573 GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
574 GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
575 /*
576 * Decrement the reference count and clear the enabled
577 * bitmask when the last listener on an event goes away.
578 */
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000579 if (--i915->pmu.enable_count[bit] == 0) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000580 i915->pmu.enable &= ~BIT_ULL(bit);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000581 i915->pmu.timer_enabled &= pmu_needs_timer(i915, true);
582 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000583
584 spin_unlock_irqrestore(&i915->pmu.lock, flags);
585}
586
587static void i915_pmu_event_start(struct perf_event *event, int flags)
588{
589 i915_pmu_enable(event);
590 event->hw.state = 0;
591}
592
593static void i915_pmu_event_stop(struct perf_event *event, int flags)
594{
595 if (flags & PERF_EF_UPDATE)
596 i915_pmu_event_read(event);
597 i915_pmu_disable(event);
598 event->hw.state = PERF_HES_STOPPED;
599}
600
601static int i915_pmu_event_add(struct perf_event *event, int flags)
602{
603 if (flags & PERF_EF_START)
604 i915_pmu_event_start(event, flags);
605
606 return 0;
607}
608
609static void i915_pmu_event_del(struct perf_event *event, int flags)
610{
611 i915_pmu_event_stop(event, PERF_EF_UPDATE);
612}
613
614static int i915_pmu_event_event_idx(struct perf_event *event)
615{
616 return 0;
617}
618
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000619struct i915_str_attribute {
620 struct device_attribute attr;
621 const char *str;
622};
623
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000624static ssize_t i915_pmu_format_show(struct device *dev,
625 struct device_attribute *attr, char *buf)
626{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000627 struct i915_str_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000628
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000629 eattr = container_of(attr, struct i915_str_attribute, attr);
630 return sprintf(buf, "%s\n", eattr->str);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000631}
632
633#define I915_PMU_FORMAT_ATTR(_name, _config) \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000634 (&((struct i915_str_attribute[]) { \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000635 { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000636 .str = _config, } \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000637 })[0].attr.attr)
638
639static struct attribute *i915_pmu_format_attrs[] = {
640 I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"),
641 NULL,
642};
643
644static const struct attribute_group i915_pmu_format_attr_group = {
645 .name = "format",
646 .attrs = i915_pmu_format_attrs,
647};
648
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000649struct i915_ext_attribute {
650 struct device_attribute attr;
651 unsigned long val;
652};
653
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000654static ssize_t i915_pmu_event_show(struct device *dev,
655 struct device_attribute *attr, char *buf)
656{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000657 struct i915_ext_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000658
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000659 eattr = container_of(attr, struct i915_ext_attribute, attr);
660 return sprintf(buf, "config=0x%lx\n", eattr->val);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000661}
662
663#define I915_EVENT_ATTR(_name, _config) \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000664 (&((struct i915_ext_attribute[]) { \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000665 { .attr = __ATTR(_name, 0444, i915_pmu_event_show, NULL), \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000666 .val = _config, } \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000667 })[0].attr.attr)
668
669#define I915_EVENT_STR(_name, _str) \
670 (&((struct perf_pmu_events_attr[]) { \
671 { .attr = __ATTR(_name, 0444, perf_event_sysfs_show, NULL), \
672 .id = 0, \
673 .event_str = _str, } \
674 })[0].attr.attr)
675
676#define I915_EVENT(_name, _config, _unit) \
677 I915_EVENT_ATTR(_name, _config), \
678 I915_EVENT_STR(_name.unit, _unit)
679
680#define I915_ENGINE_EVENT(_name, _class, _instance, _sample) \
681 I915_EVENT_ATTR(_name, __I915_PMU_ENGINE(_class, _instance, _sample)), \
682 I915_EVENT_STR(_name.unit, "ns")
683
684#define I915_ENGINE_EVENTS(_name, _class, _instance) \
685 I915_ENGINE_EVENT(_name##_instance-busy, _class, _instance, I915_SAMPLE_BUSY), \
686 I915_ENGINE_EVENT(_name##_instance-sema, _class, _instance, I915_SAMPLE_SEMA), \
687 I915_ENGINE_EVENT(_name##_instance-wait, _class, _instance, I915_SAMPLE_WAIT)
688
689static struct attribute *i915_pmu_events_attrs[] = {
690 I915_ENGINE_EVENTS(rcs, I915_ENGINE_CLASS_RENDER, 0),
691 I915_ENGINE_EVENTS(bcs, I915_ENGINE_CLASS_COPY, 0),
692 I915_ENGINE_EVENTS(vcs, I915_ENGINE_CLASS_VIDEO, 0),
693 I915_ENGINE_EVENTS(vcs, I915_ENGINE_CLASS_VIDEO, 1),
694 I915_ENGINE_EVENTS(vecs, I915_ENGINE_CLASS_VIDEO_ENHANCE, 0),
695
696 I915_EVENT(actual-frequency, I915_PMU_ACTUAL_FREQUENCY, "MHz"),
697 I915_EVENT(requested-frequency, I915_PMU_REQUESTED_FREQUENCY, "MHz"),
698
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000699 I915_EVENT_ATTR(interrupts, I915_PMU_INTERRUPTS),
700
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000701 I915_EVENT(rc6-residency, I915_PMU_RC6_RESIDENCY, "ns"),
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000702
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000703 NULL,
704};
705
706static const struct attribute_group i915_pmu_events_attr_group = {
707 .name = "events",
708 .attrs = i915_pmu_events_attrs,
709};
710
711static ssize_t
712i915_pmu_get_attr_cpumask(struct device *dev,
713 struct device_attribute *attr,
714 char *buf)
715{
716 return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask);
717}
718
719static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL);
720
721static struct attribute *i915_cpumask_attrs[] = {
722 &dev_attr_cpumask.attr,
723 NULL,
724};
725
726static struct attribute_group i915_pmu_cpumask_attr_group = {
727 .attrs = i915_cpumask_attrs,
728};
729
730static const struct attribute_group *i915_pmu_attr_groups[] = {
731 &i915_pmu_format_attr_group,
732 &i915_pmu_events_attr_group,
733 &i915_pmu_cpumask_attr_group,
734 NULL
735};
736
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000737static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
738{
739 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000740
741 GEM_BUG_ON(!pmu->base.event_init);
742
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000743 /* Select the first online CPU as a designated reader. */
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000744 if (!cpumask_weight(&i915_pmu_cpumask))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000745 cpumask_set_cpu(cpu, &i915_pmu_cpumask);
746
747 return 0;
748}
749
750static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
751{
752 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
753 unsigned int target;
754
755 GEM_BUG_ON(!pmu->base.event_init);
756
757 if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) {
758 target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
759 /* Migrate events if there is a valid target */
760 if (target < nr_cpu_ids) {
761 cpumask_set_cpu(target, &i915_pmu_cpumask);
762 perf_pmu_migrate_context(&pmu->base, cpu, target);
763 }
764 }
765
766 return 0;
767}
768
769static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000770
771static int i915_pmu_register_cpuhp_state(struct drm_i915_private *i915)
772{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000773 enum cpuhp_state slot;
774 int ret;
775
776 ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
777 "perf/x86/intel/i915:online",
778 i915_pmu_cpu_online,
779 i915_pmu_cpu_offline);
780 if (ret < 0)
781 return ret;
782
783 slot = ret;
784 ret = cpuhp_state_add_instance(slot, &i915->pmu.node);
785 if (ret) {
786 cpuhp_remove_multi_state(slot);
787 return ret;
788 }
789
790 cpuhp_slot = slot;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000791 return 0;
792}
793
794static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915)
795{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000796 WARN_ON(cpuhp_slot == CPUHP_INVALID);
797 WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &i915->pmu.node));
798 cpuhp_remove_multi_state(cpuhp_slot);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000799}
800
801void i915_pmu_register(struct drm_i915_private *i915)
802{
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000803 struct intel_engine_cs *engine;
804 enum intel_engine_id id;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000805 int ret;
806
807 if (INTEL_GEN(i915) <= 2) {
808 DRM_INFO("PMU not supported for this GPU.");
809 return;
810 }
811
812 i915->pmu.base.attr_groups = i915_pmu_attr_groups;
813 i915->pmu.base.task_ctx_nr = perf_invalid_context;
814 i915->pmu.base.event_init = i915_pmu_event_init;
815 i915->pmu.base.add = i915_pmu_event_add;
816 i915->pmu.base.del = i915_pmu_event_del;
817 i915->pmu.base.start = i915_pmu_event_start;
818 i915->pmu.base.stop = i915_pmu_event_stop;
819 i915->pmu.base.read = i915_pmu_event_read;
820 i915->pmu.base.event_idx = i915_pmu_event_event_idx;
821
822 spin_lock_init(&i915->pmu.lock);
823 hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
824 i915->pmu.timer.function = i915_sample;
825
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000826 for_each_engine(engine, i915, id)
827 INIT_DELAYED_WORK(&engine->pmu.disable_busy_stats,
828 __disable_busy_stats);
829
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000830 ret = perf_pmu_register(&i915->pmu.base, "i915", -1);
831 if (ret)
832 goto err;
833
834 ret = i915_pmu_register_cpuhp_state(i915);
835 if (ret)
836 goto err_unreg;
837
838 return;
839
840err_unreg:
841 perf_pmu_unregister(&i915->pmu.base);
842err:
843 i915->pmu.base.event_init = NULL;
844 DRM_NOTE("Failed to register PMU! (err=%d)\n", ret);
845}
846
847void i915_pmu_unregister(struct drm_i915_private *i915)
848{
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000849 struct intel_engine_cs *engine;
850 enum intel_engine_id id;
851
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000852 if (!i915->pmu.base.event_init)
853 return;
854
855 WARN_ON(i915->pmu.enable);
856
857 hrtimer_cancel(&i915->pmu.timer);
858
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000859 for_each_engine(engine, i915, id) {
860 GEM_BUG_ON(engine->pmu.busy_stats);
861 flush_delayed_work(&engine->pmu.disable_busy_stats);
862 }
863
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000864 i915_pmu_unregister_cpuhp_state(i915);
865
866 perf_pmu_unregister(&i915->pmu.base);
867 i915->pmu.base.event_init = NULL;
868}