1 /*        $NetBSD: i915_pmu.h,v 1.2 2021/12/18 23:45:28 riastradh Exp $         */
2 
3 /*
4  * SPDX-License-Identifier: MIT
5  *
6  * Copyright © 2017-2018 Intel Corporation
7  */
8 
9 #ifndef __I915_PMU_H__
10 #define __I915_PMU_H__
11 
12 #include <linux/hrtimer.h>
13 #include <linux/perf_event.h>
14 #include <linux/spinlock_types.h>
15 #include <drm/i915_drm.h>
16 
17 struct drm_i915_private;
18 
19 enum {
20           __I915_SAMPLE_FREQ_ACT = 0,
21           __I915_SAMPLE_FREQ_REQ,
22           __I915_SAMPLE_RC6,
23           __I915_SAMPLE_RC6_LAST_REPORTED,
24           __I915_NUM_PMU_SAMPLERS
25 };
26 
27 /**
28  * How many different events we track in the global PMU mask.
29  *
30  * It is also used to know to needed number of event reference counters.
31  */
32 #define I915_PMU_MASK_BITS \
33           ((1 << I915_PMU_SAMPLE_BITS) + \
34            (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0)))
35 
36 #define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
37 
38 struct i915_pmu_sample {
39           u64 cur;
40 };
41 
42 struct i915_pmu {
43           /**
44            * @node: List node for CPU hotplug handling.
45            */
46           struct hlist_node node;
47           /**
48            * @base: PMU base.
49            */
50           struct pmu base;
51           /**
52            * @name: Name as registered with perf core.
53            */
54           const char *name;
55           /**
56            * @lock: Lock protecting enable mask and ref count handling.
57            */
58           spinlock_t lock;
59           /**
60            * @timer: Timer for internal i915 PMU sampling.
61            */
62           struct hrtimer timer;
63           /**
64            * @enable: Bitmask of all currently enabled events.
65            *
66            * Bits are derived from uAPI event numbers in a way that low 16 bits
67            * correspond to engine event _sample_ _type_ (I915_SAMPLE_QUEUED is
68            * bit 0), and higher bits correspond to other events (for instance
69            * I915_PMU_ACTUAL_FREQUENCY is bit 16 etc).
70            *
71            * In other words, low 16 bits are not per engine but per engine
72            * sampler type, while the upper bits are directly mapped to other
73            * event types.
74            */
75           u64 enable;
76 
77           /**
78            * @timer_last:
79            *
80            * Timestmap of the previous timer invocation.
81            */
82           ktime_t timer_last;
83 
84           /**
85            * @enable_count: Reference counts for the enabled events.
86            *
87            * Array indices are mapped in the same way as bits in the @enable field
88            * and they are used to control sampling on/off when multiple clients
89            * are using the PMU API.
90            */
91           unsigned int enable_count[I915_PMU_MASK_BITS];
92           /**
93            * @timer_enabled: Should the internal sampling timer be running.
94            */
95           bool timer_enabled;
96           /**
97            * @sample: Current and previous (raw) counters for sampling events.
98            *
99            * These counters are updated from the i915 PMU sampling timer.
100            *
101            * Only global counters are held here, while the per-engine ones are in
102            * struct intel_engine_cs.
103            */
104           struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS];
105           /**
106            * @sleep_last: Last time GT parked for RC6 estimation.
107            */
108           ktime_t sleep_last;
109           /**
110            * @i915_attr: Memory block holding device attributes.
111            */
112           void *i915_attr;
113           /**
114            * @pmu_attr: Memory block holding device attributes.
115            */
116           void *pmu_attr;
117 };
118 
119 #ifdef CONFIG_PERF_EVENTS
120 void i915_pmu_register(struct drm_i915_private *i915);
121 void i915_pmu_unregister(struct drm_i915_private *i915);
122 void i915_pmu_gt_parked(struct drm_i915_private *i915);
123 void i915_pmu_gt_unparked(struct drm_i915_private *i915);
124 #else
i915_pmu_register(struct drm_i915_private * i915)125 static inline void i915_pmu_register(struct drm_i915_private *i915) {}
i915_pmu_unregister(struct drm_i915_private * i915)126 static inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
i915_pmu_gt_parked(struct drm_i915_private * i915)127 static inline void i915_pmu_gt_parked(struct drm_i915_private *i915) {}
i915_pmu_gt_unparked(struct drm_i915_private * i915)128 static inline void i915_pmu_gt_unparked(struct drm_i915_private *i915) {}
129 #endif
130 
131 #endif
132