blob: 00fe401868c4fb41417e1bf9a8595c9d21b07f3c [file] [log] [blame]
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001/*
Michal Wajdeczko058a9b42018-03-08 09:50:36 +00002 * SPDX-License-Identifier: MIT
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00003 *
Michal Wajdeczko058a9b42018-03-08 09:50:36 +00004 * Copyright © 2017-2018 Intel Corporation
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00005 */
6
Nicolai Stange447ae312018-07-29 12:15:33 +02007#include <linux/irq.h>
Vincent Guittot3b4ed2e2018-12-21 11:33:55 +01008#include <linux/pm_runtime.h>
Chris Wilson112ed2d2019-04-24 18:48:39 +01009
10#include "gt/intel_engine.h"
Chris Wilson51fbd8de2019-08-02 00:36:16 +010011#include "gt/intel_engine_pm.h"
Chris Wilson750e76b2019-08-06 13:43:00 +010012#include "gt/intel_engine_user.h"
Chris Wilson51fbd8de2019-08-02 00:36:16 +010013#include "gt/intel_gt_pm.h"
Andi Shytic1132362019-09-27 12:08:49 +010014#include "gt/intel_rc6.h"
Chris Wilson112ed2d2019-04-24 18:48:39 +010015
Michal Wajdeczko058a9b42018-03-08 09:50:36 +000016#include "i915_drv.h"
Jani Nikulaecbb5fb2019-04-29 15:29:37 +030017#include "i915_pmu.h"
18#include "intel_pm.h"
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +000019
20/* Frequency for the sampling timer for events which need it. */
21#define FREQUENCY 200
22#define PERIOD max_t(u64, 10000, NSEC_PER_SEC / FREQUENCY)
23
24#define ENGINE_SAMPLE_MASK \
25 (BIT(I915_SAMPLE_BUSY) | \
26 BIT(I915_SAMPLE_WAIT) | \
27 BIT(I915_SAMPLE_SEMA))
28
29#define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
30
Chris Wilson141a0892017-11-23 12:34:31 +000031static cpumask_t i915_pmu_cpumask;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +000032
33static u8 engine_config_sample(u64 config)
34{
35 return config & I915_PMU_SAMPLE_MASK;
36}
37
38static u8 engine_event_sample(struct perf_event *event)
39{
40 return engine_config_sample(event->attr.config);
41}
42
43static u8 engine_event_class(struct perf_event *event)
44{
45 return (event->attr.config >> I915_PMU_CLASS_SHIFT) & 0xff;
46}
47
48static u8 engine_event_instance(struct perf_event *event)
49{
50 return (event->attr.config >> I915_PMU_SAMPLE_BITS) & 0xff;
51}
52
53static bool is_engine_config(u64 config)
54{
55 return config < __I915_PMU_OTHER(0);
56}
57
58static unsigned int config_enabled_bit(u64 config)
59{
60 if (is_engine_config(config))
61 return engine_config_sample(config);
62 else
63 return ENGINE_SAMPLE_BITS + (config - __I915_PMU_OTHER(0));
64}
65
66static u64 config_enabled_mask(u64 config)
67{
68 return BIT_ULL(config_enabled_bit(config));
69}
70
71static bool is_engine_event(struct perf_event *event)
72{
73 return is_engine_config(event->attr.config);
74}
75
76static unsigned int event_enabled_bit(struct perf_event *event)
77{
78 return config_enabled_bit(event->attr.config);
79}
80
Tvrtko Ursulin908091c2019-08-01 17:23:27 +010081static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +000082{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +010083 struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +000084 u64 enable;
85
86 /*
87 * Only some counters need the sampling timer.
88 *
89 * We start with a bitmask of all currently enabled events.
90 */
Tvrtko Ursulin908091c2019-08-01 17:23:27 +010091 enable = pmu->enable;
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +000092
93 /*
94 * Mask out all the ones which do not need the timer, or in
95 * other words keep all the ones that could need the timer.
96 */
97 enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
98 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
99 ENGINE_SAMPLE_MASK;
100
101 /*
102 * When the GPU is idle per-engine counters do not need to be
103 * running so clear those bits out.
104 */
105 if (!gpu_active)
106 enable &= ~ENGINE_SAMPLE_MASK;
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000107 /*
108 * Also there is software busyness tracking available we do not
109 * need the timer for I915_SAMPLE_BUSY counter.
110 */
Chris Wilsonbf73fc02019-07-03 15:37:02 +0100111 else if (i915->caps.scheduler & I915_SCHEDULER_CAP_ENGINE_BUSY_STATS)
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000112 enable &= ~BIT(I915_SAMPLE_BUSY);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000113
114 /*
115 * If some bits remain it means we need the sampling timer running.
116 */
117 return enable;
118}
119
Andi Shytic1132362019-09-27 12:08:49 +0100120static u64 __get_rc6(struct intel_gt *gt)
Chris Wilson16ffe732019-09-12 13:48:13 +0100121{
122 struct drm_i915_private *i915 = gt->i915;
123 u64 val;
124
Andi Shytic1132362019-09-27 12:08:49 +0100125 val = intel_rc6_residency_ns(&gt->rc6,
Chris Wilson16ffe732019-09-12 13:48:13 +0100126 IS_VALLEYVIEW(i915) ?
127 VLV_GT_RENDER_RC6 :
128 GEN6_GT_GFX_RC6);
129
130 if (HAS_RC6p(i915))
Andi Shytic1132362019-09-27 12:08:49 +0100131 val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6p);
Chris Wilson16ffe732019-09-12 13:48:13 +0100132
133 if (HAS_RC6pp(i915))
Andi Shytic1132362019-09-27 12:08:49 +0100134 val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6pp);
Chris Wilson16ffe732019-09-12 13:48:13 +0100135
136 return val;
137}
138
139#if IS_ENABLED(CONFIG_PM)
140
141static inline s64 ktime_since(const ktime_t kt)
142{
143 return ktime_to_ns(ktime_sub(ktime_get(), kt));
144}
145
146static u64 __pmu_estimate_rc6(struct i915_pmu *pmu)
147{
148 u64 val;
149
150 /*
151 * We think we are runtime suspended.
152 *
153 * Report the delta from when the device was suspended to now,
154 * on top of the last known real value, as the approximated RC6
155 * counter value.
156 */
157 val = ktime_since(pmu->sleep_last);
158 val += pmu->sample[__I915_SAMPLE_RC6].cur;
159
160 pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
161
162 return val;
163}
164
165static u64 __pmu_update_rc6(struct i915_pmu *pmu, u64 val)
166{
167 /*
168 * If we are coming back from being runtime suspended we must
169 * be careful not to report a larger value than returned
170 * previously.
171 */
172 if (val >= pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur) {
173 pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0;
174 pmu->sample[__I915_SAMPLE_RC6].cur = val;
175 } else {
176 val = pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur;
177 }
178
179 return val;
180}
181
182static u64 get_rc6(struct intel_gt *gt)
183{
184 struct drm_i915_private *i915 = gt->i915;
185 struct i915_pmu *pmu = &i915->pmu;
186 unsigned long flags;
187 u64 val;
188
189 val = 0;
190 if (intel_gt_pm_get_if_awake(gt)) {
191 val = __get_rc6(gt);
192 intel_gt_pm_put(gt);
193 }
194
195 spin_lock_irqsave(&pmu->lock, flags);
196
197 if (val)
198 val = __pmu_update_rc6(pmu, val);
199 else
200 val = __pmu_estimate_rc6(pmu);
201
202 spin_unlock_irqrestore(&pmu->lock, flags);
203
204 return val;
205}
206
207static void park_rc6(struct drm_i915_private *i915)
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000208{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100209 struct i915_pmu *pmu = &i915->pmu;
210
Chris Wilson16ffe732019-09-12 13:48:13 +0100211 if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
212 __pmu_update_rc6(pmu, __get_rc6(&i915->gt));
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000213
Chris Wilson16ffe732019-09-12 13:48:13 +0100214 pmu->sleep_last = ktime_get();
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000215}
216
Chris Wilson16ffe732019-09-12 13:48:13 +0100217static void unpark_rc6(struct drm_i915_private *i915)
218{
219 struct i915_pmu *pmu = &i915->pmu;
220
221 /* Estimate how long we slept and accumulate that into rc6 counters */
222 if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
223 __pmu_estimate_rc6(pmu);
224}
225
226#else
227
228static u64 get_rc6(struct intel_gt *gt)
229{
230 return __get_rc6(gt);
231}
232
233static void park_rc6(struct drm_i915_private *i915) {}
234static void unpark_rc6(struct drm_i915_private *i915) {}
235
236#endif
237
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100238static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000239{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100240 if (!pmu->timer_enabled && pmu_needs_timer(pmu, true)) {
241 pmu->timer_enabled = true;
242 pmu->timer_last = ktime_get();
243 hrtimer_start_range_ns(&pmu->timer,
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000244 ns_to_ktime(PERIOD), 0,
245 HRTIMER_MODE_REL_PINNED);
246 }
247}
248
Chris Wilson16ffe732019-09-12 13:48:13 +0100249void i915_pmu_gt_parked(struct drm_i915_private *i915)
250{
251 struct i915_pmu *pmu = &i915->pmu;
252
253 if (!pmu->base.event_init)
254 return;
255
256 spin_lock_irq(&pmu->lock);
257
258 park_rc6(i915);
259
260 /*
261 * Signal sampling timer to stop if only engine events are enabled and
262 * GPU went idle.
263 */
264 pmu->timer_enabled = pmu_needs_timer(pmu, false);
265
266 spin_unlock_irq(&pmu->lock);
267}
268
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000269void i915_pmu_gt_unparked(struct drm_i915_private *i915)
270{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100271 struct i915_pmu *pmu = &i915->pmu;
272
273 if (!pmu->base.event_init)
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000274 return;
275
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100276 spin_lock_irq(&pmu->lock);
Chris Wilson16ffe732019-09-12 13:48:13 +0100277
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000278 /*
279 * Re-enable sampling timer when GPU goes active.
280 */
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100281 __i915_pmu_maybe_start_timer(pmu);
Chris Wilson16ffe732019-09-12 13:48:13 +0100282
283 unpark_rc6(i915);
284
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100285 spin_unlock_irq(&pmu->lock);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000286}
287
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000288static void
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100289add_sample(struct i915_pmu_sample *sample, u32 val)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000290{
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100291 sample->cur += val;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000292}
293
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100294static void
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100295engines_sample(struct intel_gt *gt, unsigned int period_ns)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000296{
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100297 struct drm_i915_private *i915 = gt->i915;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000298 struct intel_engine_cs *engine;
299 enum intel_engine_id id;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000300
Tvrtko Ursulin28fba092019-08-01 17:23:28 +0100301 if ((i915->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000302 return;
303
Tvrtko Ursulin28fba092019-08-01 17:23:28 +0100304 for_each_engine(engine, i915, id) {
Chris Wilsond0aa6942019-02-23 00:01:02 +0000305 struct intel_engine_pmu *pmu = &engine->pmu;
Chris Wilson51fbd8de2019-08-02 00:36:16 +0100306 unsigned long flags;
Chris Wilsond0aa6942019-02-23 00:01:02 +0000307 bool busy;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000308 u32 val;
309
Chris Wilson51fbd8de2019-08-02 00:36:16 +0100310 if (!intel_engine_pm_get_if_awake(engine))
311 continue;
312
313 spin_lock_irqsave(&engine->uncore->lock, flags);
314
Tvrtko Ursulin28fba092019-08-01 17:23:28 +0100315 val = ENGINE_READ_FW(engine, RING_CTL);
Chris Wilsond0aa6942019-02-23 00:01:02 +0000316 if (val == 0) /* powerwell off => engine idle */
Chris Wilson51fbd8de2019-08-02 00:36:16 +0100317 goto skip;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000318
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100319 if (val & RING_WAIT)
Chris Wilsond0aa6942019-02-23 00:01:02 +0000320 add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100321 if (val & RING_WAIT_SEMAPHORE)
Chris Wilsond0aa6942019-02-23 00:01:02 +0000322 add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000323
Tvrtko Ursulin54fc5772019-09-11 17:07:30 +0100324 /* No need to sample when busy stats are supported. */
325 if (intel_engine_supports_stats(engine))
326 goto skip;
327
Chris Wilsond0aa6942019-02-23 00:01:02 +0000328 /*
329 * While waiting on a semaphore or event, MI_MODE reports the
330 * ring as idle. However, previously using the seqno, and with
331 * execlists sampling, we account for the ring waiting as the
332 * engine being busy. Therefore, we record the sample as being
333 * busy if either waiting or !idle.
334 */
335 busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
336 if (!busy) {
Tvrtko Ursulin28fba092019-08-01 17:23:28 +0100337 val = ENGINE_READ_FW(engine, RING_MI_MODE);
Chris Wilsond0aa6942019-02-23 00:01:02 +0000338 busy = !(val & MODE_IDLE);
339 }
340 if (busy)
341 add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000342
Chris Wilson51fbd8de2019-08-02 00:36:16 +0100343skip:
344 spin_unlock_irqrestore(&engine->uncore->lock, flags);
345 intel_engine_pm_put(engine);
346 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000347}
348
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100349static void
350add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul)
351{
352 sample->cur += mul_u32_u32(val, mul);
353}
354
355static void
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100356frequency_sample(struct intel_gt *gt, unsigned int period_ns)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000357{
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100358 struct drm_i915_private *i915 = gt->i915;
359 struct intel_uncore *uncore = gt->uncore;
360 struct i915_pmu *pmu = &i915->pmu;
361
362 if (pmu->enable & config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000363 u32 val;
364
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100365 val = i915->gt_pm.rps.cur_freq;
Chris Wilson51fbd8de2019-08-02 00:36:16 +0100366 if (intel_gt_pm_get_if_awake(gt)) {
367 val = intel_uncore_read_notrace(uncore, GEN6_RPSTAT1);
368 val = intel_get_cagf(i915, val);
369 intel_gt_pm_put(gt);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000370 }
371
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100372 add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT],
373 intel_gpu_freq(i915, val),
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100374 period_ns / 1000);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000375 }
376
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100377 if (pmu->enable & config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
378 add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
379 intel_gpu_freq(i915, i915->gt_pm.rps.cur_freq),
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100380 period_ns / 1000);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000381 }
382}
383
384static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
385{
386 struct drm_i915_private *i915 =
387 container_of(hrtimer, struct drm_i915_private, pmu.timer);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100388 struct i915_pmu *pmu = &i915->pmu;
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100389 struct intel_gt *gt = &i915->gt;
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100390 unsigned int period_ns;
391 ktime_t now;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000392
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100393 if (!READ_ONCE(pmu->timer_enabled))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000394 return HRTIMER_NORESTART;
395
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100396 now = ktime_get();
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100397 period_ns = ktime_to_ns(ktime_sub(now, pmu->timer_last));
398 pmu->timer_last = now;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000399
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100400 /*
401 * Strictly speaking the passed in period may not be 100% accurate for
402 * all internal calculation, since some amount of time can be spent on
403 * grabbing the forcewake. However the potential error from timer call-
404 * back delay greatly dominates this so we keep it simple.
405 */
Tvrtko Ursulin08ce5c62019-08-01 17:23:29 +0100406 engines_sample(gt, period_ns);
407 frequency_sample(gt, period_ns);
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100408
409 hrtimer_forward(hrtimer, now, ns_to_ktime(PERIOD));
410
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000411 return HRTIMER_RESTART;
412}
413
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000414static u64 count_interrupts(struct drm_i915_private *i915)
415{
416 /* open-coded kstat_irqs() */
417 struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq);
418 u64 sum = 0;
419 int cpu;
420
421 if (!desc || !desc->kstat_irqs)
422 return 0;
423
424 for_each_possible_cpu(cpu)
425 sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
426
427 return sum;
428}
429
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000430static void engine_event_destroy(struct perf_event *event)
431{
432 struct drm_i915_private *i915 =
433 container_of(event->pmu, typeof(*i915), pmu.base);
434 struct intel_engine_cs *engine;
435
436 engine = intel_engine_lookup_user(i915,
437 engine_event_class(event),
438 engine_event_instance(event));
439 if (WARN_ON_ONCE(!engine))
440 return;
441
442 if (engine_event_sample(event) == I915_SAMPLE_BUSY &&
443 intel_engine_supports_stats(engine))
444 intel_disable_engine_stats(engine);
445}
446
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000447static void i915_pmu_event_destroy(struct perf_event *event)
448{
449 WARN_ON(event->parent);
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000450
451 if (is_engine_event(event))
452 engine_event_destroy(event);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000453}
454
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000455static int
456engine_event_status(struct intel_engine_cs *engine,
457 enum drm_i915_pmu_engine_sample sample)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000458{
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000459 switch (sample) {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000460 case I915_SAMPLE_BUSY:
461 case I915_SAMPLE_WAIT:
462 break;
463 case I915_SAMPLE_SEMA:
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000464 if (INTEL_GEN(engine->i915) < 6)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000465 return -ENODEV;
466 break;
467 default:
468 return -ENOENT;
469 }
470
471 return 0;
472}
473
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000474static int
475config_status(struct drm_i915_private *i915, u64 config)
476{
477 switch (config) {
478 case I915_PMU_ACTUAL_FREQUENCY:
479 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
480 /* Requires a mutex for sampling! */
481 return -ENODEV;
482 /* Fall-through. */
483 case I915_PMU_REQUESTED_FREQUENCY:
484 if (INTEL_GEN(i915) < 6)
485 return -ENODEV;
486 break;
487 case I915_PMU_INTERRUPTS:
488 break;
489 case I915_PMU_RC6_RESIDENCY:
490 if (!HAS_RC6(i915))
491 return -ENODEV;
492 break;
493 default:
494 return -ENOENT;
495 }
496
497 return 0;
498}
499
500static int engine_event_init(struct perf_event *event)
501{
502 struct drm_i915_private *i915 =
503 container_of(event->pmu, typeof(*i915), pmu.base);
504 struct intel_engine_cs *engine;
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000505 u8 sample;
506 int ret;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000507
508 engine = intel_engine_lookup_user(i915, engine_event_class(event),
509 engine_event_instance(event));
510 if (!engine)
511 return -ENODEV;
512
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000513 sample = engine_event_sample(event);
514 ret = engine_event_status(engine, sample);
515 if (ret)
516 return ret;
517
518 if (sample == I915_SAMPLE_BUSY && intel_engine_supports_stats(engine))
519 ret = intel_enable_engine_stats(engine);
520
521 return ret;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000522}
523
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000524static int i915_pmu_event_init(struct perf_event *event)
525{
526 struct drm_i915_private *i915 =
527 container_of(event->pmu, typeof(*i915), pmu.base);
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000528 int ret;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000529
530 if (event->attr.type != event->pmu->type)
531 return -ENOENT;
532
533 /* unsupported modes and filters */
534 if (event->attr.sample_period) /* no sampling */
535 return -EINVAL;
536
537 if (has_branch_stack(event))
538 return -EOPNOTSUPP;
539
540 if (event->cpu < 0)
541 return -EINVAL;
542
Tvrtko Ursulin0426c042017-11-23 12:34:32 +0000543 /* only allow running on one cpu at a time */
544 if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask))
Tvrtko Ursulin00a79722017-11-28 10:55:15 +0000545 return -EINVAL;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000546
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000547 if (is_engine_event(event))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000548 ret = engine_event_init(event);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000549 else
550 ret = config_status(i915, event->attr.config);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000551 if (ret)
552 return ret;
553
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000554 if (!event->parent)
555 event->destroy = i915_pmu_event_destroy;
556
557 return 0;
558}
559
Tvrtko Ursulinad055fb2018-03-14 08:05:35 +0000560static u64 __i915_pmu_event_read(struct perf_event *event)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000561{
562 struct drm_i915_private *i915 =
563 container_of(event->pmu, typeof(*i915), pmu.base);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100564 struct i915_pmu *pmu = &i915->pmu;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000565 u64 val = 0;
566
567 if (is_engine_event(event)) {
568 u8 sample = engine_event_sample(event);
569 struct intel_engine_cs *engine;
570
571 engine = intel_engine_lookup_user(i915,
572 engine_event_class(event),
573 engine_event_instance(event));
574
575 if (WARN_ON_ONCE(!engine)) {
576 /* Do nothing */
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000577 } else if (sample == I915_SAMPLE_BUSY &&
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000578 intel_engine_supports_stats(engine)) {
Tvrtko Ursulinb3add012017-11-21 18:18:49 +0000579 val = ktime_to_ns(intel_engine_get_busy_time(engine));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000580 } else {
581 val = engine->pmu.sample[sample].cur;
582 }
583 } else {
584 switch (event->attr.config) {
585 case I915_PMU_ACTUAL_FREQUENCY:
586 val =
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100587 div_u64(pmu->sample[__I915_SAMPLE_FREQ_ACT].cur,
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100588 USEC_PER_SEC /* to MHz */);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000589 break;
590 case I915_PMU_REQUESTED_FREQUENCY:
591 val =
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100592 div_u64(pmu->sample[__I915_SAMPLE_FREQ_REQ].cur,
Tvrtko Ursulin9f473ec2018-06-05 15:02:53 +0100593 USEC_PER_SEC /* to MHz */);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000594 break;
Tvrtko Ursulin0cd46842017-11-21 18:18:50 +0000595 case I915_PMU_INTERRUPTS:
596 val = count_interrupts(i915);
597 break;
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000598 case I915_PMU_RC6_RESIDENCY:
Tvrtko Ursulin518ea582019-08-01 17:23:30 +0100599 val = get_rc6(&i915->gt);
Tvrtko Ursulin6060b6a2017-11-21 18:18:52 +0000600 break;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000601 }
602 }
603
604 return val;
605}
606
607static void i915_pmu_event_read(struct perf_event *event)
608{
609 struct hw_perf_event *hwc = &event->hw;
610 u64 prev, new;
611
612again:
613 prev = local64_read(&hwc->prev_count);
Tvrtko Ursulinad055fb2018-03-14 08:05:35 +0000614 new = __i915_pmu_event_read(event);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000615
616 if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
617 goto again;
618
619 local64_add(new - prev, &event->count);
620}
621
622static void i915_pmu_enable(struct perf_event *event)
623{
624 struct drm_i915_private *i915 =
625 container_of(event->pmu, typeof(*i915), pmu.base);
626 unsigned int bit = event_enabled_bit(event);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100627 struct i915_pmu *pmu = &i915->pmu;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000628 unsigned long flags;
629
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100630 spin_lock_irqsave(&pmu->lock, flags);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000631
632 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000633 * Update the bitmask of enabled events and increment
634 * the event reference counter.
635 */
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100636 BUILD_BUG_ON(ARRAY_SIZE(pmu->enable_count) != I915_PMU_MASK_BITS);
637 GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
638 GEM_BUG_ON(pmu->enable_count[bit] == ~0);
639 pmu->enable |= BIT_ULL(bit);
640 pmu->enable_count[bit]++;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000641
642 /*
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000643 * Start the sampling timer if needed and not already enabled.
644 */
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100645 __i915_pmu_maybe_start_timer(pmu);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000646
647 /*
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000648 * For per-engine events the bitmask and reference counting
649 * is stored per engine.
650 */
651 if (is_engine_event(event)) {
652 u8 sample = engine_event_sample(event);
653 struct intel_engine_cs *engine;
654
655 engine = intel_engine_lookup_user(i915,
656 engine_event_class(event),
657 engine_event_instance(event));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000658
Tvrtko Ursulin26a11de2019-02-05 13:03:53 +0000659 BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
660 I915_ENGINE_SAMPLE_COUNT);
661 BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
662 I915_ENGINE_SAMPLE_COUNT);
663 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
664 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000665 GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
Tvrtko Ursulin26a11de2019-02-05 13:03:53 +0000666
667 engine->pmu.enable |= BIT(sample);
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000668 engine->pmu.enable_count[sample]++;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000669 }
670
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100671 spin_unlock_irqrestore(&pmu->lock, flags);
Tvrtko Ursulinad055fb2018-03-14 08:05:35 +0000672
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000673 /*
674 * Store the current counter value so we can report the correct delta
675 * for all listeners. Even when the event was already enabled and has
676 * an existing non-zero value.
677 */
Tvrtko Ursulinad055fb2018-03-14 08:05:35 +0000678 local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000679}
680
681static void i915_pmu_disable(struct perf_event *event)
682{
683 struct drm_i915_private *i915 =
684 container_of(event->pmu, typeof(*i915), pmu.base);
685 unsigned int bit = event_enabled_bit(event);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100686 struct i915_pmu *pmu = &i915->pmu;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000687 unsigned long flags;
688
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100689 spin_lock_irqsave(&pmu->lock, flags);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000690
691 if (is_engine_event(event)) {
692 u8 sample = engine_event_sample(event);
693 struct intel_engine_cs *engine;
694
695 engine = intel_engine_lookup_user(i915,
696 engine_event_class(event),
697 engine_event_instance(event));
Tvrtko Ursulin26a11de2019-02-05 13:03:53 +0000698
699 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
700 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000701 GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
Tvrtko Ursulin26a11de2019-02-05 13:03:53 +0000702
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000703 /*
704 * Decrement the reference count and clear the enabled
705 * bitmask when the last listener on an event goes away.
706 */
Tvrtko Ursulinb2f78cd2018-02-05 09:34:48 +0000707 if (--engine->pmu.enable_count[sample] == 0)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000708 engine->pmu.enable &= ~BIT(sample);
709 }
710
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100711 GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
712 GEM_BUG_ON(pmu->enable_count[bit] == 0);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000713 /*
714 * Decrement the reference count and clear the enabled
715 * bitmask when the last listener on an event goes away.
716 */
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100717 if (--pmu->enable_count[bit] == 0) {
718 pmu->enable &= ~BIT_ULL(bit);
719 pmu->timer_enabled &= pmu_needs_timer(pmu, true);
Tvrtko Ursulinfeff0dc2017-11-21 18:18:46 +0000720 }
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000721
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100722 spin_unlock_irqrestore(&pmu->lock, flags);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000723}
724
725static void i915_pmu_event_start(struct perf_event *event, int flags)
726{
727 i915_pmu_enable(event);
728 event->hw.state = 0;
729}
730
731static void i915_pmu_event_stop(struct perf_event *event, int flags)
732{
733 if (flags & PERF_EF_UPDATE)
734 i915_pmu_event_read(event);
735 i915_pmu_disable(event);
736 event->hw.state = PERF_HES_STOPPED;
737}
738
739static int i915_pmu_event_add(struct perf_event *event, int flags)
740{
741 if (flags & PERF_EF_START)
742 i915_pmu_event_start(event, flags);
743
744 return 0;
745}
746
747static void i915_pmu_event_del(struct perf_event *event, int flags)
748{
749 i915_pmu_event_stop(event, PERF_EF_UPDATE);
750}
751
752static int i915_pmu_event_event_idx(struct perf_event *event)
753{
754 return 0;
755}
756
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000757struct i915_str_attribute {
758 struct device_attribute attr;
759 const char *str;
760};
761
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000762static ssize_t i915_pmu_format_show(struct device *dev,
763 struct device_attribute *attr, char *buf)
764{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000765 struct i915_str_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000766
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000767 eattr = container_of(attr, struct i915_str_attribute, attr);
768 return sprintf(buf, "%s\n", eattr->str);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000769}
770
771#define I915_PMU_FORMAT_ATTR(_name, _config) \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000772 (&((struct i915_str_attribute[]) { \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000773 { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000774 .str = _config, } \
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000775 })[0].attr.attr)
776
777static struct attribute *i915_pmu_format_attrs[] = {
778 I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"),
779 NULL,
780};
781
782static const struct attribute_group i915_pmu_format_attr_group = {
783 .name = "format",
784 .attrs = i915_pmu_format_attrs,
785};
786
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000787struct i915_ext_attribute {
788 struct device_attribute attr;
789 unsigned long val;
790};
791
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000792static ssize_t i915_pmu_event_show(struct device *dev,
793 struct device_attribute *attr, char *buf)
794{
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000795 struct i915_ext_attribute *eattr;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000796
Chris Wilsonb7d3aab2017-11-23 21:17:51 +0000797 eattr = container_of(attr, struct i915_ext_attribute, attr);
798 return sprintf(buf, "config=0x%lx\n", eattr->val);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000799}
800
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000801static struct attribute_group i915_pmu_events_attr_group = {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000802 .name = "events",
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000803 /* Patch in attrs at runtime. */
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000804};
805
806static ssize_t
807i915_pmu_get_attr_cpumask(struct device *dev,
808 struct device_attribute *attr,
809 char *buf)
810{
811 return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask);
812}
813
814static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL);
815
816static struct attribute *i915_cpumask_attrs[] = {
817 &dev_attr_cpumask.attr,
818 NULL,
819};
820
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000821static const struct attribute_group i915_pmu_cpumask_attr_group = {
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +0000822 .attrs = i915_cpumask_attrs,
823};
824
825static const struct attribute_group *i915_pmu_attr_groups[] = {
826 &i915_pmu_format_attr_group,
827 &i915_pmu_events_attr_group,
828 &i915_pmu_cpumask_attr_group,
829 NULL
830};
831
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000832#define __event(__config, __name, __unit) \
833{ \
834 .config = (__config), \
835 .name = (__name), \
836 .unit = (__unit), \
837}
838
839#define __engine_event(__sample, __name) \
840{ \
841 .sample = (__sample), \
842 .name = (__name), \
843}
844
845static struct i915_ext_attribute *
846add_i915_attr(struct i915_ext_attribute *attr, const char *name, u64 config)
847{
Chris Wilson2bbba4e2018-01-11 14:04:02 +0000848 sysfs_attr_init(&attr->attr.attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000849 attr->attr.attr.name = name;
850 attr->attr.attr.mode = 0444;
851 attr->attr.show = i915_pmu_event_show;
852 attr->val = config;
853
854 return ++attr;
855}
856
857static struct perf_pmu_events_attr *
858add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,
859 const char *str)
860{
Chris Wilson2bbba4e2018-01-11 14:04:02 +0000861 sysfs_attr_init(&attr->attr.attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000862 attr->attr.attr.name = name;
863 attr->attr.attr.mode = 0444;
864 attr->attr.show = perf_event_sysfs_show;
865 attr->event_str = str;
866
867 return ++attr;
868}
869
870static struct attribute **
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100871create_event_attributes(struct i915_pmu *pmu)
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000872{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100873 struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000874 static const struct {
875 u64 config;
876 const char *name;
877 const char *unit;
878 } events[] = {
879 __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "MHz"),
880 __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "MHz"),
881 __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
882 __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
883 };
884 static const struct {
885 enum drm_i915_pmu_engine_sample sample;
886 char *name;
887 } engine_events[] = {
888 __engine_event(I915_SAMPLE_BUSY, "busy"),
889 __engine_event(I915_SAMPLE_SEMA, "sema"),
890 __engine_event(I915_SAMPLE_WAIT, "wait"),
891 };
892 unsigned int count = 0;
893 struct perf_pmu_events_attr *pmu_attr = NULL, *pmu_iter;
894 struct i915_ext_attribute *i915_attr = NULL, *i915_iter;
895 struct attribute **attr = NULL, **attr_iter;
896 struct intel_engine_cs *engine;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000897 unsigned int i;
898
899 /* Count how many counters we will be exposing. */
900 for (i = 0; i < ARRAY_SIZE(events); i++) {
901 if (!config_status(i915, events[i].config))
902 count++;
903 }
904
Chris Wilson750e76b2019-08-06 13:43:00 +0100905 for_each_uabi_engine(engine, i915) {
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000906 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
907 if (!engine_event_status(engine,
908 engine_events[i].sample))
909 count++;
910 }
911 }
912
913 /* Allocate attribute objects and table. */
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000914 i915_attr = kcalloc(count, sizeof(*i915_attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000915 if (!i915_attr)
916 goto err_alloc;
917
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000918 pmu_attr = kcalloc(count, sizeof(*pmu_attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000919 if (!pmu_attr)
920 goto err_alloc;
921
922 /* Max one pointer of each attribute type plus a termination entry. */
Tvrtko Ursulindd5fec82018-01-12 17:03:40 +0000923 attr = kcalloc(count * 2 + 1, sizeof(*attr), GFP_KERNEL);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000924 if (!attr)
925 goto err_alloc;
926
927 i915_iter = i915_attr;
928 pmu_iter = pmu_attr;
929 attr_iter = attr;
930
931 /* Initialize supported non-engine counters. */
932 for (i = 0; i < ARRAY_SIZE(events); i++) {
933 char *str;
934
935 if (config_status(i915, events[i].config))
936 continue;
937
938 str = kstrdup(events[i].name, GFP_KERNEL);
939 if (!str)
940 goto err;
941
942 *attr_iter++ = &i915_iter->attr.attr;
943 i915_iter = add_i915_attr(i915_iter, str, events[i].config);
944
945 if (events[i].unit) {
946 str = kasprintf(GFP_KERNEL, "%s.unit", events[i].name);
947 if (!str)
948 goto err;
949
950 *attr_iter++ = &pmu_iter->attr.attr;
951 pmu_iter = add_pmu_attr(pmu_iter, str, events[i].unit);
952 }
953 }
954
955 /* Initialize supported engine counters. */
Chris Wilson750e76b2019-08-06 13:43:00 +0100956 for_each_uabi_engine(engine, i915) {
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000957 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
958 char *str;
959
960 if (engine_event_status(engine,
961 engine_events[i].sample))
962 continue;
963
964 str = kasprintf(GFP_KERNEL, "%s-%s",
965 engine->name, engine_events[i].name);
966 if (!str)
967 goto err;
968
969 *attr_iter++ = &i915_iter->attr.attr;
970 i915_iter =
971 add_i915_attr(i915_iter, str,
Tvrtko Ursulin8810bc52018-01-23 13:45:58 +0000972 __I915_PMU_ENGINE(engine->uabi_class,
Chris Wilson750e76b2019-08-06 13:43:00 +0100973 engine->uabi_instance,
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000974 engine_events[i].sample));
975
976 str = kasprintf(GFP_KERNEL, "%s-%s.unit",
977 engine->name, engine_events[i].name);
978 if (!str)
979 goto err;
980
981 *attr_iter++ = &pmu_iter->attr.attr;
982 pmu_iter = add_pmu_attr(pmu_iter, str, "ns");
983 }
984 }
985
Tvrtko Ursulin908091c2019-08-01 17:23:27 +0100986 pmu->i915_attr = i915_attr;
987 pmu->pmu_attr = pmu_attr;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +0000988
989 return attr;
990
991err:;
992 for (attr_iter = attr; *attr_iter; attr_iter++)
993 kfree((*attr_iter)->name);
994
995err_alloc:
996 kfree(attr);
997 kfree(i915_attr);
998 kfree(pmu_attr);
999
1000 return NULL;
1001}
1002
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001003static void free_event_attributes(struct i915_pmu *pmu)
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001004{
1005 struct attribute **attr_iter = i915_pmu_events_attr_group.attrs;
1006
1007 for (; *attr_iter; attr_iter++)
1008 kfree((*attr_iter)->name);
1009
1010 kfree(i915_pmu_events_attr_group.attrs);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001011 kfree(pmu->i915_attr);
1012 kfree(pmu->pmu_attr);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001013
1014 i915_pmu_events_attr_group.attrs = NULL;
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001015 pmu->i915_attr = NULL;
1016 pmu->pmu_attr = NULL;
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001017}
1018
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001019static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
1020{
1021 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001022
1023 GEM_BUG_ON(!pmu->base.event_init);
1024
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001025 /* Select the first online CPU as a designated reader. */
Tvrtko Ursulin0426c042017-11-23 12:34:32 +00001026 if (!cpumask_weight(&i915_pmu_cpumask))
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001027 cpumask_set_cpu(cpu, &i915_pmu_cpumask);
1028
1029 return 0;
1030}
1031
1032static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
1033{
1034 struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
1035 unsigned int target;
1036
1037 GEM_BUG_ON(!pmu->base.event_init);
1038
1039 if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) {
1040 target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
1041 /* Migrate events if there is a valid target */
1042 if (target < nr_cpu_ids) {
1043 cpumask_set_cpu(target, &i915_pmu_cpumask);
1044 perf_pmu_migrate_context(&pmu->base, cpu, target);
1045 }
1046 }
1047
1048 return 0;
1049}
1050
1051static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001052
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001053static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001054{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001055 enum cpuhp_state slot;
1056 int ret;
1057
1058 ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
1059 "perf/x86/intel/i915:online",
1060 i915_pmu_cpu_online,
1061 i915_pmu_cpu_offline);
1062 if (ret < 0)
1063 return ret;
1064
1065 slot = ret;
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001066 ret = cpuhp_state_add_instance(slot, &pmu->node);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001067 if (ret) {
1068 cpuhp_remove_multi_state(slot);
1069 return ret;
1070 }
1071
1072 cpuhp_slot = slot;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001073 return 0;
1074}
1075
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001076static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001077{
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001078 WARN_ON(cpuhp_slot == CPUHP_INVALID);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001079 WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &pmu->node));
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001080 cpuhp_remove_multi_state(cpuhp_slot);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001081}
1082
Tvrtko Ursulin05488672019-10-16 10:38:02 +01001083static bool is_igp(struct drm_i915_private *i915)
1084{
1085 struct pci_dev *pdev = i915->drm.pdev;
1086
1087 /* IGP is 0000:00:02.0 */
1088 return pci_domain_nr(pdev->bus) == 0 &&
1089 pdev->bus->number == 0 &&
1090 PCI_SLOT(pdev->devfn) == 2 &&
1091 PCI_FUNC(pdev->devfn) == 0;
1092}
1093
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001094void i915_pmu_register(struct drm_i915_private *i915)
1095{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001096 struct i915_pmu *pmu = &i915->pmu;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001097 int ret;
1098
1099 if (INTEL_GEN(i915) <= 2) {
Chris Wilson88f80652019-08-15 10:36:04 +01001100 dev_info(i915->drm.dev, "PMU not supported for this GPU.");
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001101 return;
1102 }
1103
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001104 i915_pmu_events_attr_group.attrs = create_event_attributes(pmu);
Tvrtko Ursulin109ec552018-01-11 08:35:25 +00001105 if (!i915_pmu_events_attr_group.attrs) {
1106 ret = -ENOMEM;
1107 goto err;
1108 }
1109
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001110 pmu->base.attr_groups = i915_pmu_attr_groups;
1111 pmu->base.task_ctx_nr = perf_invalid_context;
1112 pmu->base.event_init = i915_pmu_event_init;
1113 pmu->base.add = i915_pmu_event_add;
1114 pmu->base.del = i915_pmu_event_del;
1115 pmu->base.start = i915_pmu_event_start;
1116 pmu->base.stop = i915_pmu_event_stop;
1117 pmu->base.read = i915_pmu_event_read;
1118 pmu->base.event_idx = i915_pmu_event_event_idx;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001119
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001120 spin_lock_init(&pmu->lock);
1121 hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1122 pmu->timer.function = i915_sample;
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001123
Tvrtko Ursulin05488672019-10-16 10:38:02 +01001124 if (!is_igp(i915))
1125 pmu->name = kasprintf(GFP_KERNEL,
1126 "i915-%s",
1127 dev_name(i915->drm.dev));
1128 else
1129 pmu->name = "i915";
1130 if (!pmu->name)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001131 goto err;
1132
Tvrtko Ursulin05488672019-10-16 10:38:02 +01001133 ret = perf_pmu_register(&pmu->base, pmu->name, -1);
1134 if (ret)
1135 goto err_name;
1136
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001137 ret = i915_pmu_register_cpuhp_state(pmu);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001138 if (ret)
1139 goto err_unreg;
1140
1141 return;
1142
1143err_unreg:
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001144 perf_pmu_unregister(&pmu->base);
Tvrtko Ursulin05488672019-10-16 10:38:02 +01001145err_name:
1146 if (!is_igp(i915))
1147 kfree(pmu->name);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001148err:
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001149 pmu->base.event_init = NULL;
1150 free_event_attributes(pmu);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001151 DRM_NOTE("Failed to register PMU! (err=%d)\n", ret);
1152}
1153
1154void i915_pmu_unregister(struct drm_i915_private *i915)
1155{
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001156 struct i915_pmu *pmu = &i915->pmu;
1157
1158 if (!pmu->base.event_init)
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001159 return;
1160
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001161 WARN_ON(pmu->enable);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001162
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001163 hrtimer_cancel(&pmu->timer);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001164
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001165 i915_pmu_unregister_cpuhp_state(pmu);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001166
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001167 perf_pmu_unregister(&pmu->base);
1168 pmu->base.event_init = NULL;
Tvrtko Ursulin05488672019-10-16 10:38:02 +01001169 if (!is_igp(i915))
1170 kfree(pmu->name);
Tvrtko Ursulin908091c2019-08-01 17:23:27 +01001171 free_event_attributes(pmu);
Tvrtko Ursulinb46a33e2017-11-21 18:18:45 +00001172}