xref: /linux/drivers/gpu/drm/msm/msm_perfcntr.h (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4  */
5 
6 #ifndef __MSM_PERFCNTR_H__
7 #define __MSM_PERFCNTR_H__
8 
9 #include "linux/array_size.h"
10 #include "linux/circ_buf.h"
11 #include "linux/hrtimer.h"
12 #include "linux/kthread.h"
13 #include "linux/wait.h"
14 #include "linux/workqueue.h"
15 
16 #include "adreno_common.xml.h"
17 
18 /*
19  * This is a subset of the tables used by mesa.  We don't need to
20  * enumerate the countables on the kernel side.
21  */
22 
23 /* Describes a single counter: */
24 struct msm_perfcntr_counter {
25 	/* offset of the SELect register to choose what to count: */
26 	unsigned select_reg;
27 	/* additional SEL regs to enable slice counters (gen8+) */
28 	unsigned slice_select_regs[2];
29 	/* offset of the lo/hi 32b to read current counter value: */
30 	unsigned counter_reg_lo;
31 	unsigned counter_reg_hi;
32 	/* TODO some counters have enable/clear registers */
33 };
34 
35 /* Describes an entire counter group: */
36 struct msm_perfcntr_group {
37 	const char *name;
38 	enum adreno_pipe pipe;
39 	unsigned num_counters;
40 	const struct msm_perfcntr_counter *counters;
41 };
42 
43 /**
44  * struct msm_perfcntr_stream - state for a single open stream fd
45  */
46 struct msm_perfcntr_stream {
47 	/** @gpu: Back-link to the GPU */
48 	struct msm_gpu *gpu;
49 
50 	/** @sample_timer: Timer to sample counters */
51 	struct hrtimer sample_timer;
52 
53 	/** @poll_wq: Wait queue for waiting for OA data to be available */
54 	wait_queue_head_t poll_wq;
55 
56 	/** @sample_period_ns: Sampling period */
57 	uint64_t sample_period_ns;
58 
59 	/** @nr_groups: # of counter groups with enabled counters */
60 	uint32_t nr_groups;
61 
62 	/** @seqno: counter for collected samples */
63 	uint32_t seqno;
64 
65 	/** @sel_fence: Fence for SEL reg programming  */
66 	uint32_t sel_fence;
67 
68 	/**
69 	 * @sel_work: Worker for SEL reg programming
70 	 *
71 	 * Initial SEL reg programming (as opposed to restoring the SEL
72 	 * regs on runpm resume) must run on the same ordered wq as is
73 	 * used by drm_sched, to serialize it with GEM_SUBMITs written
74 	 * into the same ringbuffer.
75 	 */
76 	struct work_struct sel_work;
77 
78 	/**
79 	 * @sample_work: Worker for collecting samples
80 	 */
81 	struct kthread_work sample_work;
82 
83 	/**
84 	 * @read_lock:
85 	 *
86 	 * Fifo access is synchronied on the producer side by virtue
87 	 * of there being a single timer collecting samples and writing
88 	 * into the fifo.  It is protected on the consumer side by
89 	 * @read_lock.
90 	 */
91 	struct mutex read_lock;
92 
93 	/**
94 	 * @group_idx: array of nr_groups
95 	 *
96 	 * Maps the order of groups in PERFCNTR_CONFIG ioctl to group idx,
97 	 * so that results in the results stream can be ordered to match
98 	 * the ioctl call that setup the stream
99 	 */
100 	uint32_t *group_idx;
101 
102 	/** @fifo: circular buffer for samples */
103 	struct circ_buf fifo;
104 
105 	/** @fifo_size: circular buffer size */
106 	size_t fifo_size;
107 
108 	/** @period_size: size of data for single sampling period */
109 	size_t period_size;
110 };
111 
112 uint32_t msm_perfcntr_group_idx(const struct msm_perfcntr_stream *stream, uint32_t n);
113 uint32_t msm_perfcntr_counter_base(const struct msm_perfcntr_stream *stream, uint32_t group_idx);
114 
115 /**
116  * struct msm_perfcntr_context_state - per-msm_context counter state
117  *
118  * A given counter can either be unused, reserved for global counter
119  * collection exclusively, or reserved for local per-context counter
120  * collection inclusively.  Multiple contexts can reserve the same
121  * counter, since SEL reg programming and counter begin/end sampling
122  * happen locally (within a single GEM_SUBMIT ioctl).
123  */
124 struct msm_perfcntr_context_state {
125 	/** @dummy: Some compilers dislike structs with only a flex array */
126 	unsigned dummy;
127 
128 	/**
129 	 * @reserved_counters:
130 	 *
131 	 * The number of reserved counters indexed by perfcntr group.
132 	 */
133 	unsigned reserved_counters[];
134 };
135 
136 extern const struct msm_perfcntr_group a6xx_perfcntr_groups[];
137 extern const unsigned a6xx_num_perfcntr_groups;
138 
139 extern const struct msm_perfcntr_group a7xx_perfcntr_groups[];
140 extern const unsigned a7xx_num_perfcntr_groups;
141 
142 extern const struct msm_perfcntr_group a8xx_perfcntr_groups[];
143 extern const unsigned a8xx_num_perfcntr_groups;
144 
145 #define GROUP(_name, _pipe, _counters, _countables) {                          \
146       .name = _name,                                                           \
147       .pipe = _pipe,                                                           \
148       .num_counters = ARRAY_SIZE(_counters),                                   \
149       .counters = _counters,                                                   \
150    }
151 
152 #define fd_perfcntr_counter msm_perfcntr_counter
153 #define fd_perfcntr_group   msm_perfcntr_group
154 
155 #endif /* __MSM_PERFCNTR_H__ */
156