Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : *
4 : : * Copyright © 2017-2018 Intel Corporation
5 : : */
6 : :
7 : : #include <linux/irq.h>
8 : : #include <linux/pm_runtime.h>
9 : :
10 : : #include "gt/intel_engine.h"
11 : : #include "gt/intel_engine_pm.h"
12 : : #include "gt/intel_engine_user.h"
13 : : #include "gt/intel_gt_pm.h"
14 : : #include "gt/intel_rc6.h"
15 : : #include "gt/intel_rps.h"
16 : :
17 : : #include "i915_drv.h"
18 : : #include "i915_pmu.h"
19 : : #include "intel_pm.h"
20 : :
21 : : /* Frequency for the sampling timer for events which need it. */
22 : : #define FREQUENCY 200
23 : : #define PERIOD max_t(u64, 10000, NSEC_PER_SEC / FREQUENCY)
24 : :
25 : : #define ENGINE_SAMPLE_MASK \
26 : : (BIT(I915_SAMPLE_BUSY) | \
27 : : BIT(I915_SAMPLE_WAIT) | \
28 : : BIT(I915_SAMPLE_SEMA))
29 : :
30 : : #define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
31 : :
32 : : static cpumask_t i915_pmu_cpumask;
33 : :
34 : 0 : static u8 engine_config_sample(u64 config)
35 : : {
36 : 0 : return config & I915_PMU_SAMPLE_MASK;
37 : : }
38 : :
39 : 0 : static u8 engine_event_sample(struct perf_event *event)
40 : : {
41 : 0 : return engine_config_sample(event->attr.config);
42 : : }
43 : :
44 : 0 : static u8 engine_event_class(struct perf_event *event)
45 : : {
46 : 0 : return (event->attr.config >> I915_PMU_CLASS_SHIFT) & 0xff;
47 : : }
48 : :
49 : 0 : static u8 engine_event_instance(struct perf_event *event)
50 : : {
51 : 0 : return (event->attr.config >> I915_PMU_SAMPLE_BITS) & 0xff;
52 : : }
53 : :
54 : 0 : static bool is_engine_config(u64 config)
55 : : {
56 : 0 : return config < __I915_PMU_OTHER(0);
57 : : }
58 : :
59 : 0 : static unsigned int config_enabled_bit(u64 config)
60 : : {
61 : 0 : if (is_engine_config(config))
62 : 0 : return engine_config_sample(config);
63 : : else
64 : 0 : return ENGINE_SAMPLE_BITS + (config - __I915_PMU_OTHER(0));
65 : : }
66 : :
67 : 0 : static u64 config_enabled_mask(u64 config)
68 : : {
69 : 0 : return BIT_ULL(config_enabled_bit(config));
70 : : }
71 : :
72 : 0 : static bool is_engine_event(struct perf_event *event)
73 : : {
74 : 0 : return is_engine_config(event->attr.config);
75 : : }
76 : :
77 : 0 : static unsigned int event_enabled_bit(struct perf_event *event)
78 : : {
79 : 0 : return config_enabled_bit(event->attr.config);
80 : : }
81 : :
82 : 0 : static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
83 : : {
84 : 0 : struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
85 : 0 : u64 enable;
86 : :
87 : : /*
88 : : * Only some counters need the sampling timer.
89 : : *
90 : : * We start with a bitmask of all currently enabled events.
91 : : */
92 : 0 : enable = pmu->enable;
93 : :
94 : : /*
95 : : * Mask out all the ones which do not need the timer, or in
96 : : * other words keep all the ones that could need the timer.
97 : : */
98 : 0 : enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
99 : : config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
100 : : ENGINE_SAMPLE_MASK;
101 : :
102 : : /*
103 : : * When the GPU is idle per-engine counters do not need to be
104 : : * running so clear those bits out.
105 : : */
106 : 0 : if (!gpu_active)
107 : 0 : enable &= ~ENGINE_SAMPLE_MASK;
108 : : /*
109 : : * Also there is software busyness tracking available we do not
110 : : * need the timer for I915_SAMPLE_BUSY counter.
111 : : */
112 [ # # ]: 0 : else if (i915->caps.scheduler & I915_SCHEDULER_CAP_ENGINE_BUSY_STATS)
113 : 0 : enable &= ~BIT(I915_SAMPLE_BUSY);
114 : :
115 : : /*
116 : : * If some bits remain it means we need the sampling timer running.
117 : : */
118 : 0 : return enable;
119 : : }
120 : :
121 : 0 : static u64 __get_rc6(struct intel_gt *gt)
122 : : {
123 : 0 : struct drm_i915_private *i915 = gt->i915;
124 : 0 : u64 val;
125 : :
126 [ # # ]: 0 : val = intel_rc6_residency_ns(>->rc6,
127 : : IS_VALLEYVIEW(i915) ?
128 : : VLV_GT_RENDER_RC6 :
129 : : GEN6_GT_GFX_RC6);
130 : :
131 [ # # ]: 0 : if (HAS_RC6p(i915))
132 : 0 : val += intel_rc6_residency_ns(>->rc6, GEN6_GT_GFX_RC6p);
133 : :
134 : 0 : if (HAS_RC6pp(i915))
135 : : val += intel_rc6_residency_ns(>->rc6, GEN6_GT_GFX_RC6pp);
136 : :
137 : 0 : return val;
138 : : }
139 : :
140 : : #if IS_ENABLED(CONFIG_PM)
141 : :
142 : 0 : static inline s64 ktime_since(const ktime_t kt)
143 : : {
144 : 0 : return ktime_to_ns(ktime_sub(ktime_get(), kt));
145 : : }
146 : :
147 : 0 : static u64 get_rc6(struct intel_gt *gt)
148 : : {
149 : 0 : struct drm_i915_private *i915 = gt->i915;
150 : 0 : struct i915_pmu *pmu = &i915->pmu;
151 : 0 : unsigned long flags;
152 : 0 : bool awake = false;
153 : 0 : u64 val;
154 : :
155 [ # # ]: 0 : if (intel_gt_pm_get_if_awake(gt)) {
156 : 0 : val = __get_rc6(gt);
157 : 0 : intel_gt_pm_put_async(gt);
158 : 0 : awake = true;
159 : : }
160 : :
161 : 0 : spin_lock_irqsave(&pmu->lock, flags);
162 : :
163 [ # # ]: 0 : if (awake) {
164 : 0 : pmu->sample[__I915_SAMPLE_RC6].cur = val;
165 : : } else {
166 : : /*
167 : : * We think we are runtime suspended.
168 : : *
169 : : * Report the delta from when the device was suspended to now,
170 : : * on top of the last known real value, as the approximated RC6
171 : : * counter value.
172 : : */
173 : 0 : val = ktime_since(pmu->sleep_last);
174 : 0 : val += pmu->sample[__I915_SAMPLE_RC6].cur;
175 : : }
176 : :
177 [ # # ]: 0 : if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur)
178 : : val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur;
179 : : else
180 : 0 : pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val;
181 : :
182 : 0 : spin_unlock_irqrestore(&pmu->lock, flags);
183 : :
184 : 0 : return val;
185 : : }
186 : :
187 : 0 : static void park_rc6(struct drm_i915_private *i915)
188 : : {
189 : 0 : struct i915_pmu *pmu = &i915->pmu;
190 : :
191 [ # # ]: 0 : if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
192 : 0 : pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
193 : :
194 : 0 : pmu->sleep_last = ktime_get();
195 : 0 : }
196 : :
197 : : #else
198 : :
199 : : static u64 get_rc6(struct intel_gt *gt)
200 : : {
201 : : return __get_rc6(gt);
202 : : }
203 : :
204 : : static void park_rc6(struct drm_i915_private *i915) {}
205 : :
206 : : #endif
207 : :
208 : 0 : static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
209 : : {
210 [ # # # # ]: 0 : if (!pmu->timer_enabled && pmu_needs_timer(pmu, true)) {
211 : 0 : pmu->timer_enabled = true;
212 : 0 : pmu->timer_last = ktime_get();
213 : 0 : hrtimer_start_range_ns(&pmu->timer,
214 : : ns_to_ktime(PERIOD), 0,
215 : : HRTIMER_MODE_REL_PINNED);
216 : : }
217 : 0 : }
218 : :
219 : 0 : void i915_pmu_gt_parked(struct drm_i915_private *i915)
220 : : {
221 : 0 : struct i915_pmu *pmu = &i915->pmu;
222 : :
223 [ # # ]: 0 : if (!pmu->base.event_init)
224 : : return;
225 : :
226 : 0 : spin_lock_irq(&pmu->lock);
227 : :
228 : 0 : park_rc6(i915);
229 : :
230 : : /*
231 : : * Signal sampling timer to stop if only engine events are enabled and
232 : : * GPU went idle.
233 : : */
234 : 0 : pmu->timer_enabled = pmu_needs_timer(pmu, false);
235 : :
236 : 0 : spin_unlock_irq(&pmu->lock);
237 : : }
238 : :
239 : 0 : void i915_pmu_gt_unparked(struct drm_i915_private *i915)
240 : : {
241 : 0 : struct i915_pmu *pmu = &i915->pmu;
242 : :
243 [ # # ]: 0 : if (!pmu->base.event_init)
244 : : return;
245 : :
246 : 0 : spin_lock_irq(&pmu->lock);
247 : :
248 : : /*
249 : : * Re-enable sampling timer when GPU goes active.
250 : : */
251 : 0 : __i915_pmu_maybe_start_timer(pmu);
252 : :
253 : 0 : spin_unlock_irq(&pmu->lock);
254 : : }
255 : :
256 : : static void
257 : 0 : add_sample(struct i915_pmu_sample *sample, u32 val)
258 : : {
259 : 0 : sample->cur += val;
260 : 0 : }
261 : :
262 : 0 : static bool exclusive_mmio_access(const struct drm_i915_private *i915)
263 : : {
264 : : /*
265 : : * We have to avoid concurrent mmio cache line access on gen7 or
266 : : * risk a machine hang. For a fun history lesson dig out the old
267 : : * userspace intel_gpu_top and run it on Ivybridge or Haswell!
268 : : */
269 : 0 : return IS_GEN(i915, 7);
270 : : }
271 : :
272 : : static void
273 : 0 : engines_sample(struct intel_gt *gt, unsigned int period_ns)
274 : : {
275 : 0 : struct drm_i915_private *i915 = gt->i915;
276 : 0 : struct intel_engine_cs *engine;
277 : 0 : enum intel_engine_id id;
278 : :
279 [ # # ]: 0 : if ((i915->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
280 : : return;
281 : :
282 [ # # ]: 0 : if (!intel_gt_pm_is_awake(gt))
283 : : return;
284 : :
285 [ # # # # ]: 0 : for_each_engine(engine, gt, id) {
286 : 0 : struct intel_engine_pmu *pmu = &engine->pmu;
287 : 0 : spinlock_t *mmio_lock;
288 : 0 : unsigned long flags;
289 : 0 : bool busy;
290 : 0 : u32 val;
291 : :
292 [ # # ]: 0 : if (!intel_engine_pm_get_if_awake(engine))
293 : 0 : continue;
294 : :
295 : 0 : mmio_lock = NULL;
296 [ # # ]: 0 : if (exclusive_mmio_access(i915))
297 : 0 : mmio_lock = &engine->uncore->lock;
298 : :
299 [ # # ]: 0 : if (unlikely(mmio_lock))
300 : 0 : spin_lock_irqsave(mmio_lock, flags);
301 : :
302 : 0 : val = ENGINE_READ_FW(engine, RING_CTL);
303 [ # # ]: 0 : if (val == 0) /* powerwell off => engine idle */
304 : 0 : goto skip;
305 : :
306 [ # # ]: 0 : if (val & RING_WAIT)
307 : 0 : add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
308 [ # # ]: 0 : if (val & RING_WAIT_SEMAPHORE)
309 : 0 : add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
310 : :
311 : : /* No need to sample when busy stats are supported. */
312 [ # # ]: 0 : if (intel_engine_supports_stats(engine))
313 : 0 : goto skip;
314 : :
315 : : /*
316 : : * While waiting on a semaphore or event, MI_MODE reports the
317 : : * ring as idle. However, previously using the seqno, and with
318 : : * execlists sampling, we account for the ring waiting as the
319 : : * engine being busy. Therefore, we record the sample as being
320 : : * busy if either waiting or !idle.
321 : : */
322 : 0 : busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
323 [ # # ]: 0 : if (!busy) {
324 : 0 : val = ENGINE_READ_FW(engine, RING_MI_MODE);
325 : 0 : busy = !(val & MODE_IDLE);
326 : : }
327 [ # # ]: 0 : if (busy)
328 : 0 : add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
329 : :
330 : 0 : skip:
331 [ # # ]: 0 : if (unlikely(mmio_lock))
332 : 0 : spin_unlock_irqrestore(mmio_lock, flags);
333 : 0 : intel_engine_pm_put_async(engine);
334 : : }
335 : : }
336 : :
337 : : static void
338 : 0 : add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul)
339 : : {
340 : 0 : sample->cur += mul_u32_u32(val, mul);
341 : 0 : }
342 : :
343 : 0 : static bool frequency_sampling_enabled(struct i915_pmu *pmu)
344 : : {
345 : 0 : return pmu->enable &
346 : : (config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
347 : : config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY));
348 : : }
349 : :
350 : : static void
351 : 0 : frequency_sample(struct intel_gt *gt, unsigned int period_ns)
352 : : {
353 : 0 : struct drm_i915_private *i915 = gt->i915;
354 : 0 : struct intel_uncore *uncore = gt->uncore;
355 : 0 : struct i915_pmu *pmu = &i915->pmu;
356 : 0 : struct intel_rps *rps = >->rps;
357 : :
358 [ # # ]: 0 : if (!frequency_sampling_enabled(pmu))
359 : : return;
360 : :
361 : : /* Report 0/0 (actual/requested) frequency while parked. */
362 [ # # ]: 0 : if (!intel_gt_pm_get_if_awake(gt))
363 : : return;
364 : :
365 [ # # ]: 0 : if (pmu->enable & config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
366 : 0 : u32 val;
367 : :
368 : : /*
369 : : * We take a quick peek here without using forcewake
370 : : * so that we don't perturb the system under observation
371 : : * (forcewake => !rc6 => increased power use). We expect
372 : : * that if the read fails because it is outside of the
373 : : * mmio power well, then it will return 0 -- in which
374 : : * case we assume the system is running at the intended
375 : : * frequency. Fortunately, the read should rarely fail!
376 : : */
377 : 0 : val = intel_uncore_read_fw(uncore, GEN6_RPSTAT1);
378 [ # # ]: 0 : if (val)
379 : 0 : val = intel_rps_get_cagf(rps, val);
380 : : else
381 : 0 : val = rps->cur_freq;
382 : :
383 : 0 : add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT],
384 : 0 : intel_gpu_freq(rps, val), period_ns / 1000);
385 : : }
386 : :
387 [ # # ]: 0 : if (pmu->enable & config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
388 : 0 : add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
389 : 0 : intel_gpu_freq(rps, rps->cur_freq),
390 : : period_ns / 1000);
391 : : }
392 : :
393 : 0 : intel_gt_pm_put_async(gt);
394 : : }
395 : :
396 : 0 : static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
397 : : {
398 : 0 : struct drm_i915_private *i915 =
399 : 0 : container_of(hrtimer, struct drm_i915_private, pmu.timer);
400 : 0 : struct i915_pmu *pmu = &i915->pmu;
401 : 0 : struct intel_gt *gt = &i915->gt;
402 : 0 : unsigned int period_ns;
403 : 0 : ktime_t now;
404 : :
405 [ # # ]: 0 : if (!READ_ONCE(pmu->timer_enabled))
406 : : return HRTIMER_NORESTART;
407 : :
408 : 0 : now = ktime_get();
409 : 0 : period_ns = ktime_to_ns(ktime_sub(now, pmu->timer_last));
410 : 0 : pmu->timer_last = now;
411 : :
412 : : /*
413 : : * Strictly speaking the passed in period may not be 100% accurate for
414 : : * all internal calculation, since some amount of time can be spent on
415 : : * grabbing the forcewake. However the potential error from timer call-
416 : : * back delay greatly dominates this so we keep it simple.
417 : : */
418 : 0 : engines_sample(gt, period_ns);
419 : 0 : frequency_sample(gt, period_ns);
420 : :
421 : 0 : hrtimer_forward(hrtimer, now, ns_to_ktime(PERIOD));
422 : :
423 : 0 : return HRTIMER_RESTART;
424 : : }
425 : :
426 : : static u64 count_interrupts(struct drm_i915_private *i915)
427 : : {
428 : : /* open-coded kstat_irqs() */
429 : : struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq);
430 : : u64 sum = 0;
431 : : int cpu;
432 : :
433 : : if (!desc || !desc->kstat_irqs)
434 : : return 0;
435 : :
436 : : for_each_possible_cpu(cpu)
437 : : sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
438 : :
439 : : return sum;
440 : : }
441 : :
442 : 0 : static void engine_event_destroy(struct perf_event *event)
443 : : {
444 : 0 : struct drm_i915_private *i915 =
445 : 0 : container_of(event->pmu, typeof(*i915), pmu.base);
446 : 0 : struct intel_engine_cs *engine;
447 : :
448 : 0 : engine = intel_engine_lookup_user(i915,
449 : : engine_event_class(event),
450 : 0 : engine_event_instance(event));
451 [ # # # # : 0 : if (WARN_ON_ONCE(!engine))
# # ]
452 : : return;
453 : :
454 [ # # # # ]: 0 : if (engine_event_sample(event) == I915_SAMPLE_BUSY &&
455 [ # # ]: 0 : intel_engine_supports_stats(engine))
456 : 0 : intel_disable_engine_stats(engine);
457 : : }
458 : :
459 : 0 : static void i915_pmu_event_destroy(struct perf_event *event)
460 : : {
461 [ # # ]: 0 : WARN_ON(event->parent);
462 : :
463 [ # # ]: 0 : if (is_engine_event(event))
464 : 0 : engine_event_destroy(event);
465 : 0 : }
466 : :
467 : : static int
468 : 0 : engine_event_status(struct intel_engine_cs *engine,
469 : : enum drm_i915_pmu_engine_sample sample)
470 : : {
471 : 0 : switch (sample) {
472 : : case I915_SAMPLE_BUSY:
473 : : case I915_SAMPLE_WAIT:
474 : : break;
475 : 0 : case I915_SAMPLE_SEMA:
476 [ # # # # : 0 : if (INTEL_GEN(engine->i915) < 6)
# # ]
477 : : return -ENODEV;
478 : : break;
479 : : default:
480 : : return -ENOENT;
481 : : }
482 : :
483 : 0 : return 0;
484 : : }
485 : :
486 : : static int
487 : 0 : config_status(struct drm_i915_private *i915, u64 config)
488 : : {
489 [ # # # # : 0 : switch (config) {
# ]
490 : : case I915_PMU_ACTUAL_FREQUENCY:
491 [ # # # # ]: 0 : if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
492 : : /* Requires a mutex for sampling! */
493 : 0 : return -ENODEV;
494 : : /* Fall-through. */
495 : : case I915_PMU_REQUESTED_FREQUENCY:
496 [ # # ]: 0 : if (INTEL_GEN(i915) < 6)
497 : 0 : return -ENODEV;
498 : : break;
499 : : case I915_PMU_INTERRUPTS:
500 : : break;
501 : 0 : case I915_PMU_RC6_RESIDENCY:
502 [ # # ]: 0 : if (!HAS_RC6(i915))
503 : 0 : return -ENODEV;
504 : : break;
505 : : default:
506 : : return -ENOENT;
507 : : }
508 : :
509 : : return 0;
510 : : }
511 : :
512 : 0 : static int engine_event_init(struct perf_event *event)
513 : : {
514 : 0 : struct drm_i915_private *i915 =
515 : 0 : container_of(event->pmu, typeof(*i915), pmu.base);
516 : 0 : struct intel_engine_cs *engine;
517 : 0 : u8 sample;
518 : 0 : int ret;
519 : :
520 : 0 : engine = intel_engine_lookup_user(i915, engine_event_class(event),
521 : 0 : engine_event_instance(event));
522 [ # # ]: 0 : if (!engine)
523 : : return -ENODEV;
524 : :
525 : 0 : sample = engine_event_sample(event);
526 [ # # # ]: 0 : ret = engine_event_status(engine, sample);
527 : 0 : if (ret)
528 : 0 : return ret;
529 : :
530 [ # # # # ]: 0 : if (sample == I915_SAMPLE_BUSY && intel_engine_supports_stats(engine))
531 : 0 : ret = intel_enable_engine_stats(engine);
532 : :
533 : : return ret;
534 : : }
535 : :
536 : 0 : static int i915_pmu_event_init(struct perf_event *event)
537 : : {
538 : 0 : struct drm_i915_private *i915 =
539 : 0 : container_of(event->pmu, typeof(*i915), pmu.base);
540 : 0 : int ret;
541 : :
542 [ # # ]: 0 : if (event->attr.type != event->pmu->type)
543 : : return -ENOENT;
544 : :
545 : : /* unsupported modes and filters */
546 [ # # ]: 0 : if (event->attr.sample_period) /* no sampling */
547 : : return -EINVAL;
548 : :
549 [ # # ]: 0 : if (has_branch_stack(event))
550 : : return -EOPNOTSUPP;
551 : :
552 [ # # ]: 0 : if (event->cpu < 0)
553 : : return -EINVAL;
554 : :
555 : : /* only allow running on one cpu at a time */
556 [ # # ]: 0 : if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask))
557 : : return -EINVAL;
558 : :
559 [ # # ]: 0 : if (is_engine_event(event))
560 : 0 : ret = engine_event_init(event);
561 : : else
562 : 0 : ret = config_status(i915, event->attr.config);
563 [ # # ]: 0 : if (ret)
564 : : return ret;
565 : :
566 [ # # ]: 0 : if (!event->parent)
567 : 0 : event->destroy = i915_pmu_event_destroy;
568 : :
569 : : return 0;
570 : : }
571 : :
572 : 0 : static u64 __i915_pmu_event_read(struct perf_event *event)
573 : : {
574 : 0 : struct drm_i915_private *i915 =
575 : 0 : container_of(event->pmu, typeof(*i915), pmu.base);
576 : 0 : struct i915_pmu *pmu = &i915->pmu;
577 : 0 : u64 val = 0;
578 : :
579 [ # # ]: 0 : if (is_engine_event(event)) {
580 : 0 : u8 sample = engine_event_sample(event);
581 : 0 : struct intel_engine_cs *engine;
582 : :
583 : 0 : engine = intel_engine_lookup_user(i915,
584 : : engine_event_class(event),
585 : : engine_event_instance(event));
586 : :
587 [ # # # # : 0 : if (WARN_ON_ONCE(!engine)) {
# # ]
588 : : /* Do nothing */
589 [ # # # # ]: 0 : } else if (sample == I915_SAMPLE_BUSY &&
590 [ # # ]: 0 : intel_engine_supports_stats(engine)) {
591 : 0 : val = ktime_to_ns(intel_engine_get_busy_time(engine));
592 : : } else {
593 : 0 : val = engine->pmu.sample[sample].cur;
594 : : }
595 : : } else {
596 [ # # # # : 0 : switch (event->attr.config) {
# ]
597 : 0 : case I915_PMU_ACTUAL_FREQUENCY:
598 : 0 : val =
599 : 0 : div_u64(pmu->sample[__I915_SAMPLE_FREQ_ACT].cur,
600 : : USEC_PER_SEC /* to MHz */);
601 : 0 : break;
602 : 0 : case I915_PMU_REQUESTED_FREQUENCY:
603 : 0 : val =
604 : 0 : div_u64(pmu->sample[__I915_SAMPLE_FREQ_REQ].cur,
605 : : USEC_PER_SEC /* to MHz */);
606 : 0 : break;
607 : 0 : case I915_PMU_INTERRUPTS:
608 : 0 : val = count_interrupts(i915);
609 : 0 : break;
610 : 0 : case I915_PMU_RC6_RESIDENCY:
611 : 0 : val = get_rc6(&i915->gt);
612 : 0 : break;
613 : : }
614 : 0 : }
615 : :
616 : 0 : return val;
617 : : }
618 : :
619 : 0 : static void i915_pmu_event_read(struct perf_event *event)
620 : : {
621 : 0 : struct hw_perf_event *hwc = &event->hw;
622 : 0 : u64 prev, new;
623 : :
624 : 0 : again:
625 : 0 : prev = local64_read(&hwc->prev_count);
626 : 0 : new = __i915_pmu_event_read(event);
627 : :
628 [ # # ]: 0 : if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
629 : 0 : goto again;
630 : :
631 : 0 : local64_add(new - prev, &event->count);
632 : 0 : }
633 : :
634 : 0 : static void i915_pmu_enable(struct perf_event *event)
635 : : {
636 : 0 : struct drm_i915_private *i915 =
637 : 0 : container_of(event->pmu, typeof(*i915), pmu.base);
638 [ # # ]: 0 : unsigned int bit = event_enabled_bit(event);
639 : 0 : struct i915_pmu *pmu = &i915->pmu;
640 : 0 : intel_wakeref_t wakeref;
641 : 0 : unsigned long flags;
642 : :
643 : 0 : wakeref = intel_runtime_pm_get(&i915->runtime_pm);
644 : 0 : spin_lock_irqsave(&pmu->lock, flags);
645 : :
646 : : /*
647 : : * Update the bitmask of enabled events and increment
648 : : * the event reference counter.
649 : : */
650 : 0 : BUILD_BUG_ON(ARRAY_SIZE(pmu->enable_count) != I915_PMU_MASK_BITS);
651 : 0 : GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
652 : 0 : GEM_BUG_ON(pmu->enable_count[bit] == ~0);
653 : :
654 [ # # # # ]: 0 : if (pmu->enable_count[bit] == 0 &&
655 : : config_enabled_mask(I915_PMU_RC6_RESIDENCY) & BIT_ULL(bit)) {
656 : 0 : pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = 0;
657 : 0 : pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
658 : 0 : pmu->sleep_last = ktime_get();
659 : : }
660 : :
661 : 0 : pmu->enable |= BIT_ULL(bit);
662 : 0 : pmu->enable_count[bit]++;
663 : :
664 : : /*
665 : : * Start the sampling timer if needed and not already enabled.
666 : : */
667 : 0 : __i915_pmu_maybe_start_timer(pmu);
668 : :
669 : : /*
670 : : * For per-engine events the bitmask and reference counting
671 : : * is stored per engine.
672 : : */
673 [ # # ]: 0 : if (is_engine_event(event)) {
674 : 0 : u8 sample = engine_event_sample(event);
675 : 0 : struct intel_engine_cs *engine;
676 : :
677 : 0 : engine = intel_engine_lookup_user(i915,
678 : : engine_event_class(event),
679 : : engine_event_instance(event));
680 : :
681 : 0 : BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
682 : : I915_ENGINE_SAMPLE_COUNT);
683 : 0 : BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
684 : : I915_ENGINE_SAMPLE_COUNT);
685 : 0 : GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
686 : 0 : GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
687 : 0 : GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
688 : :
689 : 0 : engine->pmu.enable |= BIT(sample);
690 : 0 : engine->pmu.enable_count[sample]++;
691 : : }
692 : :
693 : 0 : spin_unlock_irqrestore(&pmu->lock, flags);
694 : :
695 : : /*
696 : : * Store the current counter value so we can report the correct delta
697 : : * for all listeners. Even when the event was already enabled and has
698 : : * an existing non-zero value.
699 : : */
700 : 0 : local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
701 : :
702 : 0 : intel_runtime_pm_put(&i915->runtime_pm, wakeref);
703 : 0 : }
704 : :
705 : 0 : static void i915_pmu_disable(struct perf_event *event)
706 : : {
707 : 0 : struct drm_i915_private *i915 =
708 : 0 : container_of(event->pmu, typeof(*i915), pmu.base);
709 [ # # ]: 0 : unsigned int bit = event_enabled_bit(event);
710 : 0 : struct i915_pmu *pmu = &i915->pmu;
711 : 0 : unsigned long flags;
712 : :
713 : 0 : spin_lock_irqsave(&pmu->lock, flags);
714 : :
715 [ # # ]: 0 : if (is_engine_event(event)) {
716 : 0 : u8 sample = engine_event_sample(event);
717 : 0 : struct intel_engine_cs *engine;
718 : :
719 : 0 : engine = intel_engine_lookup_user(i915,
720 : : engine_event_class(event),
721 : : engine_event_instance(event));
722 : :
723 : 0 : GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
724 : 0 : GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
725 : 0 : GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
726 : :
727 : : /*
728 : : * Decrement the reference count and clear the enabled
729 : : * bitmask when the last listener on an event goes away.
730 : : */
731 [ # # ]: 0 : if (--engine->pmu.enable_count[sample] == 0)
732 : 0 : engine->pmu.enable &= ~BIT(sample);
733 : : }
734 : :
735 : 0 : GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
736 : 0 : GEM_BUG_ON(pmu->enable_count[bit] == 0);
737 : : /*
738 : : * Decrement the reference count and clear the enabled
739 : : * bitmask when the last listener on an event goes away.
740 : : */
741 [ # # ]: 0 : if (--pmu->enable_count[bit] == 0) {
742 : 0 : pmu->enable &= ~BIT_ULL(bit);
743 [ # # ]: 0 : pmu->timer_enabled &= pmu_needs_timer(pmu, true);
744 : : }
745 : :
746 : 0 : spin_unlock_irqrestore(&pmu->lock, flags);
747 : 0 : }
748 : :
749 : 0 : static void i915_pmu_event_start(struct perf_event *event, int flags)
750 : : {
751 : 0 : i915_pmu_enable(event);
752 : 0 : event->hw.state = 0;
753 : 0 : }
754 : :
755 : 0 : static void i915_pmu_event_stop(struct perf_event *event, int flags)
756 : : {
757 [ # # ]: 0 : if (flags & PERF_EF_UPDATE)
758 : 0 : i915_pmu_event_read(event);
759 : 0 : i915_pmu_disable(event);
760 : 0 : event->hw.state = PERF_HES_STOPPED;
761 : 0 : }
762 : :
763 : 0 : static int i915_pmu_event_add(struct perf_event *event, int flags)
764 : : {
765 [ # # ]: 0 : if (flags & PERF_EF_START)
766 : 0 : i915_pmu_event_start(event, flags);
767 : :
768 : 0 : return 0;
769 : : }
770 : :
771 : 0 : static void i915_pmu_event_del(struct perf_event *event, int flags)
772 : : {
773 : 0 : i915_pmu_event_stop(event, PERF_EF_UPDATE);
774 : 0 : }
775 : :
776 : 0 : static int i915_pmu_event_event_idx(struct perf_event *event)
777 : : {
778 : 0 : return 0;
779 : : }
780 : :
781 : : struct i915_str_attribute {
782 : : struct device_attribute attr;
783 : : const char *str;
784 : : };
785 : :
786 : 0 : static ssize_t i915_pmu_format_show(struct device *dev,
787 : : struct device_attribute *attr, char *buf)
788 : : {
789 : 0 : struct i915_str_attribute *eattr;
790 : :
791 : 0 : eattr = container_of(attr, struct i915_str_attribute, attr);
792 : 0 : return sprintf(buf, "%s\n", eattr->str);
793 : : }
794 : :
795 : : #define I915_PMU_FORMAT_ATTR(_name, _config) \
796 : : (&((struct i915_str_attribute[]) { \
797 : : { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \
798 : : .str = _config, } \
799 : : })[0].attr.attr)
800 : :
801 : : static struct attribute *i915_pmu_format_attrs[] = {
802 : : I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"),
803 : : NULL,
804 : : };
805 : :
806 : : static const struct attribute_group i915_pmu_format_attr_group = {
807 : : .name = "format",
808 : : .attrs = i915_pmu_format_attrs,
809 : : };
810 : :
811 : : struct i915_ext_attribute {
812 : : struct device_attribute attr;
813 : : unsigned long val;
814 : : };
815 : :
816 : 0 : static ssize_t i915_pmu_event_show(struct device *dev,
817 : : struct device_attribute *attr, char *buf)
818 : : {
819 : 0 : struct i915_ext_attribute *eattr;
820 : :
821 : 0 : eattr = container_of(attr, struct i915_ext_attribute, attr);
822 : 0 : return sprintf(buf, "config=0x%lx\n", eattr->val);
823 : : }
824 : :
825 : : static ssize_t
826 : 0 : i915_pmu_get_attr_cpumask(struct device *dev,
827 : : struct device_attribute *attr,
828 : : char *buf)
829 : : {
830 : 0 : return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask);
831 : : }
832 : :
833 : : static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL);
834 : :
835 : : static struct attribute *i915_cpumask_attrs[] = {
836 : : &dev_attr_cpumask.attr,
837 : : NULL,
838 : : };
839 : :
840 : : static const struct attribute_group i915_pmu_cpumask_attr_group = {
841 : : .attrs = i915_cpumask_attrs,
842 : : };
843 : :
844 : : #define __event(__config, __name, __unit) \
845 : : { \
846 : : .config = (__config), \
847 : : .name = (__name), \
848 : : .unit = (__unit), \
849 : : }
850 : :
851 : : #define __engine_event(__sample, __name) \
852 : : { \
853 : : .sample = (__sample), \
854 : : .name = (__name), \
855 : : }
856 : :
857 : : static struct i915_ext_attribute *
858 : 0 : add_i915_attr(struct i915_ext_attribute *attr, const char *name, u64 config)
859 : : {
860 : 0 : sysfs_attr_init(&attr->attr.attr);
861 : 0 : attr->attr.attr.name = name;
862 : 0 : attr->attr.attr.mode = 0444;
863 : 0 : attr->attr.show = i915_pmu_event_show;
864 : 0 : attr->val = config;
865 : :
866 : 0 : return ++attr;
867 : : }
868 : :
869 : : static struct perf_pmu_events_attr *
870 : 0 : add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,
871 : : const char *str)
872 : : {
873 : 0 : sysfs_attr_init(&attr->attr.attr);
874 : 0 : attr->attr.attr.name = name;
875 : 0 : attr->attr.attr.mode = 0444;
876 : 0 : attr->attr.show = perf_event_sysfs_show;
877 : 0 : attr->event_str = str;
878 : :
879 : 0 : return ++attr;
880 : : }
881 : :
882 : : static struct attribute **
883 : 0 : create_event_attributes(struct i915_pmu *pmu)
884 : : {
885 : 0 : struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
886 : 0 : static const struct {
887 : : u64 config;
888 : : const char *name;
889 : : const char *unit;
890 : : } events[] = {
891 : : __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "M"),
892 : : __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"),
893 : : __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
894 : : __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
895 : : };
896 : 0 : static const struct {
897 : : enum drm_i915_pmu_engine_sample sample;
898 : : char *name;
899 : : } engine_events[] = {
900 : : __engine_event(I915_SAMPLE_BUSY, "busy"),
901 : : __engine_event(I915_SAMPLE_SEMA, "sema"),
902 : : __engine_event(I915_SAMPLE_WAIT, "wait"),
903 : : };
904 : 0 : unsigned int count = 0;
905 : 0 : struct perf_pmu_events_attr *pmu_attr = NULL, *pmu_iter;
906 : 0 : struct i915_ext_attribute *i915_attr = NULL, *i915_iter;
907 : 0 : struct attribute **attr = NULL, **attr_iter;
908 : 0 : struct intel_engine_cs *engine;
909 : 0 : unsigned int i;
910 : :
911 : : /* Count how many counters we will be exposing. */
912 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(events); i++) {
913 [ # # ]: 0 : if (!config_status(i915, events[i].config))
914 : 0 : count++;
915 : : }
916 : :
917 [ # # # # : 0 : for_each_uabi_engine(engine, i915) {
# # ]
918 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
919 [ # # # ]: 0 : if (!engine_event_status(engine,
920 : : engine_events[i].sample))
921 : 0 : count++;
922 : : }
923 : : }
924 : :
925 : : /* Allocate attribute objects and table. */
926 : 0 : i915_attr = kcalloc(count, sizeof(*i915_attr), GFP_KERNEL);
927 [ # # ]: 0 : if (!i915_attr)
928 : 0 : goto err_alloc;
929 : :
930 : 0 : pmu_attr = kcalloc(count, sizeof(*pmu_attr), GFP_KERNEL);
931 [ # # ]: 0 : if (!pmu_attr)
932 : 0 : goto err_alloc;
933 : :
934 : : /* Max one pointer of each attribute type plus a termination entry. */
935 : 0 : attr = kcalloc(count * 2 + 1, sizeof(*attr), GFP_KERNEL);
936 [ # # ]: 0 : if (!attr)
937 : 0 : goto err_alloc;
938 : :
939 : : i915_iter = i915_attr;
940 : : pmu_iter = pmu_attr;
941 : : attr_iter = attr;
942 : :
943 : : /* Initialize supported non-engine counters. */
944 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(events); i++) {
945 : 0 : char *str;
946 : :
947 [ # # ]: 0 : if (config_status(i915, events[i].config))
948 : 0 : continue;
949 : :
950 : 0 : str = kstrdup(events[i].name, GFP_KERNEL);
951 [ # # ]: 0 : if (!str)
952 : 0 : goto err;
953 : :
954 : 0 : *attr_iter++ = &i915_iter->attr.attr;
955 : 0 : i915_iter = add_i915_attr(i915_iter, str, events[i].config);
956 : :
957 [ # # ]: 0 : if (events[i].unit) {
958 : 0 : str = kasprintf(GFP_KERNEL, "%s.unit", events[i].name);
959 [ # # ]: 0 : if (!str)
960 : 0 : goto err;
961 : :
962 : 0 : *attr_iter++ = &pmu_iter->attr.attr;
963 : 0 : pmu_iter = add_pmu_attr(pmu_iter, str, events[i].unit);
964 : : }
965 : : }
966 : :
967 : : /* Initialize supported engine counters. */
968 [ # # # # : 0 : for_each_uabi_engine(engine, i915) {
# # ]
969 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
970 : 0 : char *str;
971 : :
972 [ # # # ]: 0 : if (engine_event_status(engine,
973 : : engine_events[i].sample))
974 : 0 : continue;
975 : :
976 : 0 : str = kasprintf(GFP_KERNEL, "%s-%s",
977 : 0 : engine->name, engine_events[i].name);
978 [ # # ]: 0 : if (!str)
979 : 0 : goto err;
980 : :
981 : 0 : *attr_iter++ = &i915_iter->attr.attr;
982 : 0 : i915_iter =
983 : 0 : add_i915_attr(i915_iter, str,
984 : 0 : __I915_PMU_ENGINE(engine->uabi_class,
985 : : engine->uabi_instance,
986 : : engine_events[i].sample));
987 : :
988 : 0 : str = kasprintf(GFP_KERNEL, "%s-%s.unit",
989 : : engine->name, engine_events[i].name);
990 [ # # ]: 0 : if (!str)
991 : 0 : goto err;
992 : :
993 : 0 : *attr_iter++ = &pmu_iter->attr.attr;
994 : 0 : pmu_iter = add_pmu_attr(pmu_iter, str, "ns");
995 : : }
996 : : }
997 : :
998 : 0 : pmu->i915_attr = i915_attr;
999 : 0 : pmu->pmu_attr = pmu_attr;
1000 : :
1001 : 0 : return attr;
1002 : :
1003 : : err:;
1004 [ # # ]: 0 : for (attr_iter = attr; *attr_iter; attr_iter++)
1005 : 0 : kfree((*attr_iter)->name);
1006 : :
1007 : 0 : err_alloc:
1008 : 0 : kfree(attr);
1009 : 0 : kfree(i915_attr);
1010 : 0 : kfree(pmu_attr);
1011 : :
1012 : 0 : return NULL;
1013 : : }
1014 : :
1015 : 0 : static void free_event_attributes(struct i915_pmu *pmu)
1016 : : {
1017 : 0 : struct attribute **attr_iter = pmu->events_attr_group.attrs;
1018 : :
1019 [ # # ]: 0 : for (; *attr_iter; attr_iter++)
1020 : 0 : kfree((*attr_iter)->name);
1021 : :
1022 : 0 : kfree(pmu->events_attr_group.attrs);
1023 : 0 : kfree(pmu->i915_attr);
1024 : 0 : kfree(pmu->pmu_attr);
1025 : :
1026 : 0 : pmu->events_attr_group.attrs = NULL;
1027 : 0 : pmu->i915_attr = NULL;
1028 : 0 : pmu->pmu_attr = NULL;
1029 : 0 : }
1030 : :
1031 : 0 : static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
1032 : : {
1033 : 0 : struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
1034 : :
1035 : 0 : GEM_BUG_ON(!pmu->base.event_init);
1036 : :
1037 : : /* Select the first online CPU as a designated reader. */
1038 [ # # ]: 0 : if (!cpumask_weight(&i915_pmu_cpumask))
1039 : 0 : cpumask_set_cpu(cpu, &i915_pmu_cpumask);
1040 : :
1041 : 0 : return 0;
1042 : : }
1043 : :
1044 : 0 : static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
1045 : : {
1046 [ # # ]: 0 : struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
1047 : 0 : unsigned int target;
1048 : :
1049 : 0 : GEM_BUG_ON(!pmu->base.event_init);
1050 : :
1051 [ # # ]: 0 : if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) {
1052 : 0 : target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
1053 : : /* Migrate events if there is a valid target */
1054 [ # # ]: 0 : if (target < nr_cpu_ids) {
1055 : 0 : cpumask_set_cpu(target, &i915_pmu_cpumask);
1056 : 0 : perf_pmu_migrate_context(&pmu->base, cpu, target);
1057 : : }
1058 : : }
1059 : :
1060 : 0 : return 0;
1061 : : }
1062 : :
1063 : 0 : static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
1064 : : {
1065 : 0 : enum cpuhp_state slot;
1066 : 0 : int ret;
1067 : :
1068 : 0 : ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
1069 : : "perf/x86/intel/i915:online",
1070 : : i915_pmu_cpu_online,
1071 : : i915_pmu_cpu_offline);
1072 [ # # ]: 0 : if (ret < 0)
1073 : : return ret;
1074 : :
1075 : 0 : slot = ret;
1076 : 0 : ret = cpuhp_state_add_instance(slot, &pmu->cpuhp.node);
1077 [ # # ]: 0 : if (ret) {
1078 : 0 : cpuhp_remove_multi_state(slot);
1079 : 0 : return ret;
1080 : : }
1081 : :
1082 : 0 : pmu->cpuhp.slot = slot;
1083 : 0 : return 0;
1084 : : }
1085 : :
1086 : 0 : static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
1087 : : {
1088 [ # # ]: 0 : WARN_ON(pmu->cpuhp.slot == CPUHP_INVALID);
1089 [ # # ]: 0 : WARN_ON(cpuhp_state_remove_instance(pmu->cpuhp.slot, &pmu->cpuhp.node));
1090 : 0 : cpuhp_remove_multi_state(pmu->cpuhp.slot);
1091 : 0 : pmu->cpuhp.slot = CPUHP_INVALID;
1092 : 0 : }
1093 : :
1094 : 0 : static bool is_igp(struct drm_i915_private *i915)
1095 : : {
1096 : 0 : struct pci_dev *pdev = i915->drm.pdev;
1097 : :
1098 : : /* IGP is 0000:00:02.0 */
1099 : 0 : return pci_domain_nr(pdev->bus) == 0 &&
1100 [ # # # # : 0 : pdev->bus->number == 0 &&
# # ]
1101 [ # # # # : 0 : PCI_SLOT(pdev->devfn) == 2 &&
# # # # #
# # # ]
1102 [ # # # # : 0 : PCI_FUNC(pdev->devfn) == 0;
# # ]
1103 : : }
1104 : :
1105 : 0 : void i915_pmu_register(struct drm_i915_private *i915)
1106 : : {
1107 : 0 : struct i915_pmu *pmu = &i915->pmu;
1108 : 0 : const struct attribute_group *attr_groups[] = {
1109 : : &i915_pmu_format_attr_group,
1110 : 0 : &pmu->events_attr_group,
1111 : : &i915_pmu_cpumask_attr_group,
1112 : : NULL
1113 : : };
1114 : :
1115 : 0 : int ret = -ENOMEM;
1116 : :
1117 [ # # ]: 0 : if (INTEL_GEN(i915) <= 2) {
1118 : 0 : dev_info(i915->drm.dev, "PMU not supported for this GPU.");
1119 : 0 : return;
1120 : : }
1121 : :
1122 : 0 : spin_lock_init(&pmu->lock);
1123 : 0 : hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1124 : 0 : pmu->timer.function = i915_sample;
1125 : 0 : pmu->cpuhp.slot = CPUHP_INVALID;
1126 : :
1127 [ # # # # ]: 0 : if (!is_igp(i915)) {
1128 : 0 : pmu->name = kasprintf(GFP_KERNEL,
1129 : : "i915_%s",
1130 [ # # ]: 0 : dev_name(i915->drm.dev));
1131 [ # # ]: 0 : if (pmu->name) {
1132 : : /* tools/perf reserves colons as special. */
1133 : 0 : strreplace((char *)pmu->name, ':', '_');
1134 : : }
1135 : : } else {
1136 : 0 : pmu->name = "i915";
1137 : : }
1138 [ # # ]: 0 : if (!pmu->name)
1139 : 0 : goto err;
1140 : :
1141 : 0 : pmu->events_attr_group.name = "events";
1142 : 0 : pmu->events_attr_group.attrs = create_event_attributes(pmu);
1143 [ # # ]: 0 : if (!pmu->events_attr_group.attrs)
1144 : 0 : goto err_name;
1145 : :
1146 : 0 : pmu->base.attr_groups = kmemdup(attr_groups, sizeof(attr_groups),
1147 : : GFP_KERNEL);
1148 [ # # ]: 0 : if (!pmu->base.attr_groups)
1149 : 0 : goto err_attr;
1150 : :
1151 : 0 : pmu->base.task_ctx_nr = perf_invalid_context;
1152 : 0 : pmu->base.event_init = i915_pmu_event_init;
1153 : 0 : pmu->base.add = i915_pmu_event_add;
1154 : 0 : pmu->base.del = i915_pmu_event_del;
1155 : 0 : pmu->base.start = i915_pmu_event_start;
1156 : 0 : pmu->base.stop = i915_pmu_event_stop;
1157 : 0 : pmu->base.read = i915_pmu_event_read;
1158 : 0 : pmu->base.event_idx = i915_pmu_event_event_idx;
1159 : :
1160 : 0 : ret = perf_pmu_register(&pmu->base, pmu->name, -1);
1161 [ # # ]: 0 : if (ret)
1162 : 0 : goto err_groups;
1163 : :
1164 : 0 : ret = i915_pmu_register_cpuhp_state(pmu);
1165 [ # # ]: 0 : if (ret)
1166 : 0 : goto err_unreg;
1167 : :
1168 : : return;
1169 : :
1170 : : err_unreg:
1171 : 0 : perf_pmu_unregister(&pmu->base);
1172 : 0 : err_groups:
1173 : 0 : kfree(pmu->base.attr_groups);
1174 : 0 : err_attr:
1175 : 0 : pmu->base.event_init = NULL;
1176 : 0 : free_event_attributes(pmu);
1177 : 0 : err_name:
1178 [ # # # # ]: 0 : if (!is_igp(i915))
1179 : 0 : kfree(pmu->name);
1180 : 0 : err:
1181 : 0 : dev_notice(i915->drm.dev, "Failed to register PMU!\n");
1182 : : }
1183 : :
1184 : 0 : void i915_pmu_unregister(struct drm_i915_private *i915)
1185 : : {
1186 : 0 : struct i915_pmu *pmu = &i915->pmu;
1187 : :
1188 [ # # ]: 0 : if (!pmu->base.event_init)
1189 : : return;
1190 : :
1191 [ # # ]: 0 : WARN_ON(pmu->enable);
1192 : :
1193 : 0 : hrtimer_cancel(&pmu->timer);
1194 : :
1195 : 0 : i915_pmu_unregister_cpuhp_state(pmu);
1196 : :
1197 : 0 : perf_pmu_unregister(&pmu->base);
1198 : 0 : pmu->base.event_init = NULL;
1199 : 0 : kfree(pmu->base.attr_groups);
1200 [ # # # # ]: 0 : if (!is_igp(i915))
1201 : 0 : kfree(pmu->name);
1202 : 0 : free_event_attributes(pmu);
1203 : : }
|