Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | /* * SPDX-License-Identifier: MIT * * Copyright © 2017-2018 Intel Corporation */ #ifndef __I915_PMU_H__ #define __I915_PMU_H__ #include <linux/hrtimer.h> #include <linux/perf_event.h> #include <linux/spinlock_types.h> #include <uapi/drm/i915_drm.h> struct drm_i915_private; /** * Non-engine events that we need to track enabled-disabled transition and * current state. */ enum i915_pmu_tracked_events { __I915_PMU_ACTUAL_FREQUENCY_ENABLED = 0, __I915_PMU_REQUESTED_FREQUENCY_ENABLED, __I915_PMU_RC6_RESIDENCY_ENABLED, __I915_PMU_TRACKED_EVENT_COUNT, /* count marker */ }; /** * Slots used from the sampling timer (non-engine events) with some extras for * convenience. */ enum { __I915_SAMPLE_FREQ_ACT = 0, __I915_SAMPLE_FREQ_REQ, __I915_SAMPLE_RC6, __I915_SAMPLE_RC6_LAST_REPORTED, __I915_NUM_PMU_SAMPLERS }; /** * How many different events we track in the global PMU mask. * * It is also used to know to needed number of event reference counters. */ #define I915_PMU_MASK_BITS \ (I915_ENGINE_SAMPLE_COUNT + __I915_PMU_TRACKED_EVENT_COUNT) #define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1) struct i915_pmu_sample { u64 cur; }; struct i915_pmu { /** * @cpuhp: Struct used for CPU hotplug handling. */ struct { struct hlist_node node; unsigned int cpu; } cpuhp; /** * @base: PMU base. */ struct pmu base; /** * @closed: i915 is unregistering. */ bool closed; /** * @name: Name as registered with perf core. */ const char *name; /** * @lock: Lock protecting enable mask and ref count handling. */ spinlock_t lock; /** * @timer: Timer for internal i915 PMU sampling. */ struct hrtimer timer; /** * @enable: Bitmask of specific enabled events. * * For some events we need to track their state and do some internal * house keeping. * * Each engine event sampler type and event listed in enum * i915_pmu_tracked_events gets a bit in this field. * * Low bits are engine samplers and other events continue from there. */ u32 enable; /** * @timer_last: * * Timestmap of the previous timer invocation. */ ktime_t timer_last; /** * @enable_count: Reference counts for the enabled events. * * Array indices are mapped in the same way as bits in the @enable field * and they are used to control sampling on/off when multiple clients * are using the PMU API. */ unsigned int enable_count[I915_PMU_MASK_BITS]; /** * @timer_enabled: Should the internal sampling timer be running. */ bool timer_enabled; /** * @sample: Current and previous (raw) counters for sampling events. * * These counters are updated from the i915 PMU sampling timer. * * Only global counters are held here, while the per-engine ones are in * struct intel_engine_cs. */ struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; /** * @sleep_last: Last time GT parked for RC6 estimation. */ ktime_t sleep_last; /** * @irq_count: Number of interrupts * * Intentionally unsigned long to avoid atomics or heuristics on 32bit. * 4e9 interrupts are a lot and postprocessing can really deal with an * occasional wraparound easily. It's 32bit after all. */ unsigned long irq_count; /** * @events_attr_group: Device events attribute group. */ struct attribute_group events_attr_group; /** * @i915_attr: Memory block holding device attributes. */ void *i915_attr; /** * @pmu_attr: Memory block holding device attributes. */ void *pmu_attr; }; #ifdef CONFIG_PERF_EVENTS int i915_pmu_init(void); void i915_pmu_exit(void); void i915_pmu_register(struct drm_i915_private *i915); void i915_pmu_unregister(struct drm_i915_private *i915); void i915_pmu_gt_parked(struct drm_i915_private *i915); void i915_pmu_gt_unparked(struct drm_i915_private *i915); #else static inline int i915_pmu_init(void) { return 0; } static inline void i915_pmu_exit(void) {} static inline void i915_pmu_register(struct drm_i915_private *i915) {} static inline void i915_pmu_unregister(struct drm_i915_private *i915) {} static inline void i915_pmu_gt_parked(struct drm_i915_private *i915) {} static inline void i915_pmu_gt_unparked(struct drm_i915_private *i915) {} #endif #endif |