162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * SPDX-License-Identifier: MIT
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright © 2017-2018 Intel Corporation
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __I915_PMU_H__
862306a36Sopenharmony_ci#define __I915_PMU_H__
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/hrtimer.h>
1162306a36Sopenharmony_ci#include <linux/perf_event.h>
1262306a36Sopenharmony_ci#include <linux/spinlock_types.h>
1362306a36Sopenharmony_ci#include <uapi/drm/i915_drm.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistruct drm_i915_private;
1662306a36Sopenharmony_cistruct intel_gt;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * Non-engine events that we need to track enabled-disabled transition and
2062306a36Sopenharmony_ci * current state.
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_cienum i915_pmu_tracked_events {
2362306a36Sopenharmony_ci	__I915_PMU_ACTUAL_FREQUENCY_ENABLED = 0,
2462306a36Sopenharmony_ci	__I915_PMU_REQUESTED_FREQUENCY_ENABLED,
2562306a36Sopenharmony_ci	__I915_PMU_RC6_RESIDENCY_ENABLED,
2662306a36Sopenharmony_ci	__I915_PMU_TRACKED_EVENT_COUNT, /* count marker */
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * Slots used from the sampling timer (non-engine events) with some extras for
3162306a36Sopenharmony_ci * convenience.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_cienum {
3462306a36Sopenharmony_ci	__I915_SAMPLE_FREQ_ACT = 0,
3562306a36Sopenharmony_ci	__I915_SAMPLE_FREQ_REQ,
3662306a36Sopenharmony_ci	__I915_SAMPLE_RC6,
3762306a36Sopenharmony_ci	__I915_SAMPLE_RC6_LAST_REPORTED,
3862306a36Sopenharmony_ci	__I915_NUM_PMU_SAMPLERS
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define I915_PMU_MAX_GT 2
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/*
4462306a36Sopenharmony_ci * How many different events we track in the global PMU mask.
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * It is also used to know to needed number of event reference counters.
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ci#define I915_PMU_MASK_BITS \
4962306a36Sopenharmony_ci	(I915_ENGINE_SAMPLE_COUNT + \
5062306a36Sopenharmony_ci	 I915_PMU_MAX_GT * __I915_PMU_TRACKED_EVENT_COUNT)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct i915_pmu_sample {
5562306a36Sopenharmony_ci	u64 cur;
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct i915_pmu {
5962306a36Sopenharmony_ci	/**
6062306a36Sopenharmony_ci	 * @cpuhp: Struct used for CPU hotplug handling.
6162306a36Sopenharmony_ci	 */
6262306a36Sopenharmony_ci	struct {
6362306a36Sopenharmony_ci		struct hlist_node node;
6462306a36Sopenharmony_ci		unsigned int cpu;
6562306a36Sopenharmony_ci	} cpuhp;
6662306a36Sopenharmony_ci	/**
6762306a36Sopenharmony_ci	 * @base: PMU base.
6862306a36Sopenharmony_ci	 */
6962306a36Sopenharmony_ci	struct pmu base;
7062306a36Sopenharmony_ci	/**
7162306a36Sopenharmony_ci	 * @closed: i915 is unregistering.
7262306a36Sopenharmony_ci	 */
7362306a36Sopenharmony_ci	bool closed;
7462306a36Sopenharmony_ci	/**
7562306a36Sopenharmony_ci	 * @name: Name as registered with perf core.
7662306a36Sopenharmony_ci	 */
7762306a36Sopenharmony_ci	const char *name;
7862306a36Sopenharmony_ci	/**
7962306a36Sopenharmony_ci	 * @lock: Lock protecting enable mask and ref count handling.
8062306a36Sopenharmony_ci	 */
8162306a36Sopenharmony_ci	spinlock_t lock;
8262306a36Sopenharmony_ci	/**
8362306a36Sopenharmony_ci	 * @unparked: GT unparked mask.
8462306a36Sopenharmony_ci	 */
8562306a36Sopenharmony_ci	unsigned int unparked;
8662306a36Sopenharmony_ci	/**
8762306a36Sopenharmony_ci	 * @timer: Timer for internal i915 PMU sampling.
8862306a36Sopenharmony_ci	 */
8962306a36Sopenharmony_ci	struct hrtimer timer;
9062306a36Sopenharmony_ci	/**
9162306a36Sopenharmony_ci	 * @enable: Bitmask of specific enabled events.
9262306a36Sopenharmony_ci	 *
9362306a36Sopenharmony_ci	 * For some events we need to track their state and do some internal
9462306a36Sopenharmony_ci	 * house keeping.
9562306a36Sopenharmony_ci	 *
9662306a36Sopenharmony_ci	 * Each engine event sampler type and event listed in enum
9762306a36Sopenharmony_ci	 * i915_pmu_tracked_events gets a bit in this field.
9862306a36Sopenharmony_ci	 *
9962306a36Sopenharmony_ci	 * Low bits are engine samplers and other events continue from there.
10062306a36Sopenharmony_ci	 */
10162306a36Sopenharmony_ci	u32 enable;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/**
10462306a36Sopenharmony_ci	 * @timer_last:
10562306a36Sopenharmony_ci	 *
10662306a36Sopenharmony_ci	 * Timestmap of the previous timer invocation.
10762306a36Sopenharmony_ci	 */
10862306a36Sopenharmony_ci	ktime_t timer_last;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/**
11162306a36Sopenharmony_ci	 * @enable_count: Reference counts for the enabled events.
11262306a36Sopenharmony_ci	 *
11362306a36Sopenharmony_ci	 * Array indices are mapped in the same way as bits in the @enable field
11462306a36Sopenharmony_ci	 * and they are used to control sampling on/off when multiple clients
11562306a36Sopenharmony_ci	 * are using the PMU API.
11662306a36Sopenharmony_ci	 */
11762306a36Sopenharmony_ci	unsigned int enable_count[I915_PMU_MASK_BITS];
11862306a36Sopenharmony_ci	/**
11962306a36Sopenharmony_ci	 * @timer_enabled: Should the internal sampling timer be running.
12062306a36Sopenharmony_ci	 */
12162306a36Sopenharmony_ci	bool timer_enabled;
12262306a36Sopenharmony_ci	/**
12362306a36Sopenharmony_ci	 * @sample: Current and previous (raw) counters for sampling events.
12462306a36Sopenharmony_ci	 *
12562306a36Sopenharmony_ci	 * These counters are updated from the i915 PMU sampling timer.
12662306a36Sopenharmony_ci	 *
12762306a36Sopenharmony_ci	 * Only global counters are held here, while the per-engine ones are in
12862306a36Sopenharmony_ci	 * struct intel_engine_cs.
12962306a36Sopenharmony_ci	 */
13062306a36Sopenharmony_ci	struct i915_pmu_sample sample[I915_PMU_MAX_GT][__I915_NUM_PMU_SAMPLERS];
13162306a36Sopenharmony_ci	/**
13262306a36Sopenharmony_ci	 * @sleep_last: Last time GT parked for RC6 estimation.
13362306a36Sopenharmony_ci	 */
13462306a36Sopenharmony_ci	ktime_t sleep_last[I915_PMU_MAX_GT];
13562306a36Sopenharmony_ci	/**
13662306a36Sopenharmony_ci	 * @irq_count: Number of interrupts
13762306a36Sopenharmony_ci	 *
13862306a36Sopenharmony_ci	 * Intentionally unsigned long to avoid atomics or heuristics on 32bit.
13962306a36Sopenharmony_ci	 * 4e9 interrupts are a lot and postprocessing can really deal with an
14062306a36Sopenharmony_ci	 * occasional wraparound easily. It's 32bit after all.
14162306a36Sopenharmony_ci	 */
14262306a36Sopenharmony_ci	unsigned long irq_count;
14362306a36Sopenharmony_ci	/**
14462306a36Sopenharmony_ci	 * @events_attr_group: Device events attribute group.
14562306a36Sopenharmony_ci	 */
14662306a36Sopenharmony_ci	struct attribute_group events_attr_group;
14762306a36Sopenharmony_ci	/**
14862306a36Sopenharmony_ci	 * @i915_attr: Memory block holding device attributes.
14962306a36Sopenharmony_ci	 */
15062306a36Sopenharmony_ci	void *i915_attr;
15162306a36Sopenharmony_ci	/**
15262306a36Sopenharmony_ci	 * @pmu_attr: Memory block holding device attributes.
15362306a36Sopenharmony_ci	 */
15462306a36Sopenharmony_ci	void *pmu_attr;
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci#ifdef CONFIG_PERF_EVENTS
15862306a36Sopenharmony_ciint i915_pmu_init(void);
15962306a36Sopenharmony_civoid i915_pmu_exit(void);
16062306a36Sopenharmony_civoid i915_pmu_register(struct drm_i915_private *i915);
16162306a36Sopenharmony_civoid i915_pmu_unregister(struct drm_i915_private *i915);
16262306a36Sopenharmony_civoid i915_pmu_gt_parked(struct intel_gt *gt);
16362306a36Sopenharmony_civoid i915_pmu_gt_unparked(struct intel_gt *gt);
16462306a36Sopenharmony_ci#else
16562306a36Sopenharmony_cistatic inline int i915_pmu_init(void) { return 0; }
16662306a36Sopenharmony_cistatic inline void i915_pmu_exit(void) {}
16762306a36Sopenharmony_cistatic inline void i915_pmu_register(struct drm_i915_private *i915) {}
16862306a36Sopenharmony_cistatic inline void i915_pmu_unregister(struct drm_i915_private *i915) {}
16962306a36Sopenharmony_cistatic inline void i915_pmu_gt_parked(struct intel_gt *gt) {}
17062306a36Sopenharmony_cistatic inline void i915_pmu_gt_unparked(struct intel_gt *gt) {}
17162306a36Sopenharmony_ci#endif
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci#endif
174