17f4dd379Sjsg /* 27f4dd379Sjsg * SPDX-License-Identifier: MIT 37f4dd379Sjsg * 47f4dd379Sjsg * Copyright © 2017-2018 Intel Corporation 57f4dd379Sjsg */ 67f4dd379Sjsg 77f4dd379Sjsg #ifndef __I915_PMU_H__ 87f4dd379Sjsg #define __I915_PMU_H__ 97f4dd379Sjsg 107f4dd379Sjsg #include <linux/hrtimer.h> 117f4dd379Sjsg #include <linux/perf_event.h> 127f4dd379Sjsg #include <linux/spinlock_types.h> 13c349dbc7Sjsg #include <uapi/drm/i915_drm.h> 147f4dd379Sjsg 157f4dd379Sjsg struct drm_i915_private; 16*f005ef32Sjsg struct intel_gt; 177f4dd379Sjsg 18*f005ef32Sjsg /* 195ca02815Sjsg * Non-engine events that we need to track enabled-disabled transition and 205ca02815Sjsg * current state. 215ca02815Sjsg */ 225ca02815Sjsg enum i915_pmu_tracked_events { 235ca02815Sjsg __I915_PMU_ACTUAL_FREQUENCY_ENABLED = 0, 245ca02815Sjsg __I915_PMU_REQUESTED_FREQUENCY_ENABLED, 255ca02815Sjsg __I915_PMU_RC6_RESIDENCY_ENABLED, 265ca02815Sjsg __I915_PMU_TRACKED_EVENT_COUNT, /* count marker */ 275ca02815Sjsg }; 285ca02815Sjsg 29*f005ef32Sjsg /* 305ca02815Sjsg * Slots used from the sampling timer (non-engine events) with some extras for 315ca02815Sjsg * convenience. 325ca02815Sjsg */ 337f4dd379Sjsg enum { 347f4dd379Sjsg __I915_SAMPLE_FREQ_ACT = 0, 357f4dd379Sjsg __I915_SAMPLE_FREQ_REQ, 367f4dd379Sjsg __I915_SAMPLE_RC6, 37c349dbc7Sjsg __I915_SAMPLE_RC6_LAST_REPORTED, 387f4dd379Sjsg __I915_NUM_PMU_SAMPLERS 397f4dd379Sjsg }; 407f4dd379Sjsg 41*f005ef32Sjsg #define I915_PMU_MAX_GT 2 42*f005ef32Sjsg 43*f005ef32Sjsg /* 447f4dd379Sjsg * How many different events we track in the global PMU mask. 457f4dd379Sjsg * 467f4dd379Sjsg * It is also used to know to needed number of event reference counters. 477f4dd379Sjsg */ 487f4dd379Sjsg #define I915_PMU_MASK_BITS \ 49*f005ef32Sjsg (I915_ENGINE_SAMPLE_COUNT + \ 50*f005ef32Sjsg I915_PMU_MAX_GT * __I915_PMU_TRACKED_EVENT_COUNT) 517f4dd379Sjsg 52c349dbc7Sjsg #define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1) 53c349dbc7Sjsg 547f4dd379Sjsg struct i915_pmu_sample { 557f4dd379Sjsg u64 cur; 567f4dd379Sjsg }; 577f4dd379Sjsg 587f4dd379Sjsg struct i915_pmu { 597f4dd379Sjsg /** 60c349dbc7Sjsg * @cpuhp: Struct used for CPU hotplug handling. 617f4dd379Sjsg */ 62c349dbc7Sjsg struct { 637f4dd379Sjsg struct hlist_node node; 645ca02815Sjsg unsigned int cpu; 65c349dbc7Sjsg } cpuhp; 667f4dd379Sjsg /** 677f4dd379Sjsg * @base: PMU base. 687f4dd379Sjsg */ 697f4dd379Sjsg struct pmu base; 707f4dd379Sjsg /** 715ca02815Sjsg * @closed: i915 is unregistering. 725ca02815Sjsg */ 735ca02815Sjsg bool closed; 745ca02815Sjsg /** 75c349dbc7Sjsg * @name: Name as registered with perf core. 76c349dbc7Sjsg */ 77c349dbc7Sjsg const char *name; 78c349dbc7Sjsg /** 797f4dd379Sjsg * @lock: Lock protecting enable mask and ref count handling. 807f4dd379Sjsg */ 817f4dd379Sjsg spinlock_t lock; 827f4dd379Sjsg /** 83*f005ef32Sjsg * @unparked: GT unparked mask. 84*f005ef32Sjsg */ 85*f005ef32Sjsg unsigned int unparked; 86*f005ef32Sjsg /** 877f4dd379Sjsg * @timer: Timer for internal i915 PMU sampling. 887f4dd379Sjsg */ 89c349dbc7Sjsg struct hrtimer timer; 907f4dd379Sjsg /** 915ca02815Sjsg * @enable: Bitmask of specific enabled events. 927f4dd379Sjsg * 935ca02815Sjsg * For some events we need to track their state and do some internal 945ca02815Sjsg * house keeping. 957f4dd379Sjsg * 965ca02815Sjsg * Each engine event sampler type and event listed in enum 975ca02815Sjsg * i915_pmu_tracked_events gets a bit in this field. 985ca02815Sjsg * 995ca02815Sjsg * Low bits are engine samplers and other events continue from there. 1007f4dd379Sjsg */ 1015ca02815Sjsg u32 enable; 1027f4dd379Sjsg 1037f4dd379Sjsg /** 1047f4dd379Sjsg * @timer_last: 1057f4dd379Sjsg * 1067f4dd379Sjsg * Timestmap of the previous timer invocation. 1077f4dd379Sjsg */ 1087f4dd379Sjsg ktime_t timer_last; 1097f4dd379Sjsg 1107f4dd379Sjsg /** 1117f4dd379Sjsg * @enable_count: Reference counts for the enabled events. 1127f4dd379Sjsg * 1137f4dd379Sjsg * Array indices are mapped in the same way as bits in the @enable field 1147f4dd379Sjsg * and they are used to control sampling on/off when multiple clients 1157f4dd379Sjsg * are using the PMU API. 1167f4dd379Sjsg */ 1177f4dd379Sjsg unsigned int enable_count[I915_PMU_MASK_BITS]; 1187f4dd379Sjsg /** 1197f4dd379Sjsg * @timer_enabled: Should the internal sampling timer be running. 1207f4dd379Sjsg */ 1217f4dd379Sjsg bool timer_enabled; 1227f4dd379Sjsg /** 1237f4dd379Sjsg * @sample: Current and previous (raw) counters for sampling events. 1247f4dd379Sjsg * 1257f4dd379Sjsg * These counters are updated from the i915 PMU sampling timer. 1267f4dd379Sjsg * 1277f4dd379Sjsg * Only global counters are held here, while the per-engine ones are in 1287f4dd379Sjsg * struct intel_engine_cs. 1297f4dd379Sjsg */ 130*f005ef32Sjsg struct i915_pmu_sample sample[I915_PMU_MAX_GT][__I915_NUM_PMU_SAMPLERS]; 1317f4dd379Sjsg /** 132c349dbc7Sjsg * @sleep_last: Last time GT parked for RC6 estimation. 1337f4dd379Sjsg */ 134*f005ef32Sjsg ktime_t sleep_last[I915_PMU_MAX_GT]; 135c349dbc7Sjsg /** 1365ca02815Sjsg * @irq_count: Number of interrupts 1375ca02815Sjsg * 1385ca02815Sjsg * Intentionally unsigned long to avoid atomics or heuristics on 32bit. 1395ca02815Sjsg * 4e9 interrupts are a lot and postprocessing can really deal with an 1405ca02815Sjsg * occasional wraparound easily. It's 32bit after all. 1415ca02815Sjsg */ 1425ca02815Sjsg unsigned long irq_count; 1435ca02815Sjsg /** 144c349dbc7Sjsg * @events_attr_group: Device events attribute group. 145c349dbc7Sjsg */ 146c349dbc7Sjsg struct attribute_group events_attr_group; 1477f4dd379Sjsg /** 1487f4dd379Sjsg * @i915_attr: Memory block holding device attributes. 1497f4dd379Sjsg */ 1507f4dd379Sjsg void *i915_attr; 1517f4dd379Sjsg /** 1527f4dd379Sjsg * @pmu_attr: Memory block holding device attributes. 1537f4dd379Sjsg */ 1547f4dd379Sjsg void *pmu_attr; 1557f4dd379Sjsg }; 1567f4dd379Sjsg 1577f4dd379Sjsg #ifdef CONFIG_PERF_EVENTS 1585ca02815Sjsg int i915_pmu_init(void); 1595ca02815Sjsg void i915_pmu_exit(void); 1607f4dd379Sjsg void i915_pmu_register(struct drm_i915_private *i915); 1617f4dd379Sjsg void i915_pmu_unregister(struct drm_i915_private *i915); 162*f005ef32Sjsg void i915_pmu_gt_parked(struct intel_gt *gt); 163*f005ef32Sjsg void i915_pmu_gt_unparked(struct intel_gt *gt); 1647f4dd379Sjsg #else i915_pmu_init(void)1655ca02815Sjsgstatic inline int i915_pmu_init(void) { return 0; } i915_pmu_exit(void)1665ca02815Sjsgstatic inline void i915_pmu_exit(void) {} i915_pmu_register(struct drm_i915_private * i915)1677f4dd379Sjsgstatic inline void i915_pmu_register(struct drm_i915_private *i915) {} i915_pmu_unregister(struct drm_i915_private * i915)1687f4dd379Sjsgstatic inline void i915_pmu_unregister(struct drm_i915_private *i915) {} i915_pmu_gt_parked(struct intel_gt * gt)169*f005ef32Sjsgstatic inline void i915_pmu_gt_parked(struct intel_gt *gt) {} i915_pmu_gt_unparked(struct intel_gt * gt)170*f005ef32Sjsgstatic inline void i915_pmu_gt_unparked(struct intel_gt *gt) {} 1717f4dd379Sjsg #endif 1727f4dd379Sjsg 1737f4dd379Sjsg #endif 174