xref: /linux/drivers/gpu/drm/msm/msm_perfcntr.h (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
15442bafdSRob Clark // SPDX-License-Identifier: GPL-2.0
25442bafdSRob Clark /*
35442bafdSRob Clark  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
45442bafdSRob Clark  */
55442bafdSRob Clark 
65442bafdSRob Clark #ifndef __MSM_PERFCNTR_H__
75442bafdSRob Clark #define __MSM_PERFCNTR_H__
85442bafdSRob Clark 
95442bafdSRob Clark #include "linux/array_size.h"
10*a7b378c9SRob Clark #include "linux/circ_buf.h"
11*a7b378c9SRob Clark #include "linux/hrtimer.h"
12*a7b378c9SRob Clark #include "linux/kthread.h"
13*a7b378c9SRob Clark #include "linux/wait.h"
14*a7b378c9SRob Clark #include "linux/workqueue.h"
155442bafdSRob Clark 
165442bafdSRob Clark #include "adreno_common.xml.h"
175442bafdSRob Clark 
185442bafdSRob Clark /*
195442bafdSRob Clark  * This is a subset of the tables used by mesa.  We don't need to
205442bafdSRob Clark  * enumerate the countables on the kernel side.
215442bafdSRob Clark  */
225442bafdSRob Clark 
235442bafdSRob Clark /* Describes a single counter: */
245442bafdSRob Clark struct msm_perfcntr_counter {
255442bafdSRob Clark 	/* offset of the SELect register to choose what to count: */
265442bafdSRob Clark 	unsigned select_reg;
275442bafdSRob Clark 	/* additional SEL regs to enable slice counters (gen8+) */
285442bafdSRob Clark 	unsigned slice_select_regs[2];
295442bafdSRob Clark 	/* offset of the lo/hi 32b to read current counter value: */
305442bafdSRob Clark 	unsigned counter_reg_lo;
315442bafdSRob Clark 	unsigned counter_reg_hi;
325442bafdSRob Clark 	/* TODO some counters have enable/clear registers */
335442bafdSRob Clark };
345442bafdSRob Clark 
355442bafdSRob Clark /* Describes an entire counter group: */
365442bafdSRob Clark struct msm_perfcntr_group {
375442bafdSRob Clark 	const char *name;
385442bafdSRob Clark 	enum adreno_pipe pipe;
395442bafdSRob Clark 	unsigned num_counters;
405442bafdSRob Clark 	const struct msm_perfcntr_counter *counters;
415442bafdSRob Clark };
425442bafdSRob Clark 
438766dbc3SRob Clark /**
4402195633SRob Clark  * struct msm_perfcntr_stream - state for a single open stream fd
4502195633SRob Clark  */
4602195633SRob Clark struct msm_perfcntr_stream {
4702195633SRob Clark 	/** @gpu: Back-link to the GPU */
4802195633SRob Clark 	struct msm_gpu *gpu;
4902195633SRob Clark 
50*a7b378c9SRob Clark 	/** @sample_timer: Timer to sample counters */
51*a7b378c9SRob Clark 	struct hrtimer sample_timer;
52*a7b378c9SRob Clark 
53*a7b378c9SRob Clark 	/** @poll_wq: Wait queue for waiting for OA data to be available */
54*a7b378c9SRob Clark 	wait_queue_head_t poll_wq;
55*a7b378c9SRob Clark 
56*a7b378c9SRob Clark 	/** @sample_period_ns: Sampling period */
57*a7b378c9SRob Clark 	uint64_t sample_period_ns;
58*a7b378c9SRob Clark 
5902195633SRob Clark 	/** @nr_groups: # of counter groups with enabled counters */
6002195633SRob Clark 	uint32_t nr_groups;
6102195633SRob Clark 
62*a7b378c9SRob Clark 	/** @seqno: counter for collected samples */
63*a7b378c9SRob Clark 	uint32_t seqno;
64*a7b378c9SRob Clark 
655eedc8c2SRob Clark 	/** @sel_fence: Fence for SEL reg programming  */
665eedc8c2SRob Clark 	uint32_t sel_fence;
675eedc8c2SRob Clark 
6802195633SRob Clark 	/**
69*a7b378c9SRob Clark 	 * @sel_work: Worker for SEL reg programming
70*a7b378c9SRob Clark 	 *
71*a7b378c9SRob Clark 	 * Initial SEL reg programming (as opposed to restoring the SEL
72*a7b378c9SRob Clark 	 * regs on runpm resume) must run on the same ordered wq as is
73*a7b378c9SRob Clark 	 * used by drm_sched, to serialize it with GEM_SUBMITs written
74*a7b378c9SRob Clark 	 * into the same ringbuffer.
75*a7b378c9SRob Clark 	 */
76*a7b378c9SRob Clark 	struct work_struct sel_work;
77*a7b378c9SRob Clark 
78*a7b378c9SRob Clark 	/**
79*a7b378c9SRob Clark 	 * @sample_work: Worker for collecting samples
80*a7b378c9SRob Clark 	 */
81*a7b378c9SRob Clark 	struct kthread_work sample_work;
82*a7b378c9SRob Clark 
83*a7b378c9SRob Clark 	/**
84*a7b378c9SRob Clark 	 * @read_lock:
85*a7b378c9SRob Clark 	 *
86*a7b378c9SRob Clark 	 * Fifo access is synchronied on the producer side by virtue
87*a7b378c9SRob Clark 	 * of there being a single timer collecting samples and writing
88*a7b378c9SRob Clark 	 * into the fifo.  It is protected on the consumer side by
89*a7b378c9SRob Clark 	 * @read_lock.
90*a7b378c9SRob Clark 	 */
91*a7b378c9SRob Clark 	struct mutex read_lock;
92*a7b378c9SRob Clark 
93*a7b378c9SRob Clark 	/**
9402195633SRob Clark 	 * @group_idx: array of nr_groups
9502195633SRob Clark 	 *
9602195633SRob Clark 	 * Maps the order of groups in PERFCNTR_CONFIG ioctl to group idx,
9702195633SRob Clark 	 * so that results in the results stream can be ordered to match
9802195633SRob Clark 	 * the ioctl call that setup the stream
9902195633SRob Clark 	 */
10002195633SRob Clark 	uint32_t *group_idx;
101*a7b378c9SRob Clark 
102*a7b378c9SRob Clark 	/** @fifo: circular buffer for samples */
103*a7b378c9SRob Clark 	struct circ_buf fifo;
104*a7b378c9SRob Clark 
105*a7b378c9SRob Clark 	/** @fifo_size: circular buffer size */
106*a7b378c9SRob Clark 	size_t fifo_size;
107*a7b378c9SRob Clark 
108*a7b378c9SRob Clark 	/** @period_size: size of data for single sampling period */
109*a7b378c9SRob Clark 	size_t period_size;
11002195633SRob Clark };
11102195633SRob Clark 
11202195633SRob Clark uint32_t msm_perfcntr_group_idx(const struct msm_perfcntr_stream *stream, uint32_t n);
11302195633SRob Clark uint32_t msm_perfcntr_counter_base(const struct msm_perfcntr_stream *stream, uint32_t group_idx);
11402195633SRob Clark 
11502195633SRob Clark /**
1168766dbc3SRob Clark  * struct msm_perfcntr_context_state - per-msm_context counter state
1178766dbc3SRob Clark  *
1188766dbc3SRob Clark  * A given counter can either be unused, reserved for global counter
1198766dbc3SRob Clark  * collection exclusively, or reserved for local per-context counter
1208766dbc3SRob Clark  * collection inclusively.  Multiple contexts can reserve the same
1218766dbc3SRob Clark  * counter, since SEL reg programming and counter begin/end sampling
1228766dbc3SRob Clark  * happen locally (within a single GEM_SUBMIT ioctl).
1238766dbc3SRob Clark  */
1248766dbc3SRob Clark struct msm_perfcntr_context_state {
1258766dbc3SRob Clark 	/** @dummy: Some compilers dislike structs with only a flex array */
1268766dbc3SRob Clark 	unsigned dummy;
1278766dbc3SRob Clark 
1288766dbc3SRob Clark 	/**
1298766dbc3SRob Clark 	 * @reserved_counters:
1308766dbc3SRob Clark 	 *
1318766dbc3SRob Clark 	 * The number of reserved counters indexed by perfcntr group.
1328766dbc3SRob Clark 	 */
1338766dbc3SRob Clark 	unsigned reserved_counters[];
1348766dbc3SRob Clark };
1358766dbc3SRob Clark 
136c897d550SRob Clark extern const struct msm_perfcntr_group a6xx_perfcntr_groups[];
137c897d550SRob Clark extern const unsigned a6xx_num_perfcntr_groups;
138c897d550SRob Clark 
139c897d550SRob Clark extern const struct msm_perfcntr_group a7xx_perfcntr_groups[];
140c897d550SRob Clark extern const unsigned a7xx_num_perfcntr_groups;
141c897d550SRob Clark 
142c897d550SRob Clark extern const struct msm_perfcntr_group a8xx_perfcntr_groups[];
143c897d550SRob Clark extern const unsigned a8xx_num_perfcntr_groups;
144c897d550SRob Clark 
1455442bafdSRob Clark #define GROUP(_name, _pipe, _counters, _countables) {                          \
1465442bafdSRob Clark       .name = _name,                                                           \
1475442bafdSRob Clark       .pipe = _pipe,                                                           \
1485442bafdSRob Clark       .num_counters = ARRAY_SIZE(_counters),                                   \
1495442bafdSRob Clark       .counters = _counters,                                                   \
1505442bafdSRob Clark    }
1515442bafdSRob Clark 
1525442bafdSRob Clark #define fd_perfcntr_counter msm_perfcntr_counter
1535442bafdSRob Clark #define fd_perfcntr_group   msm_perfcntr_group
1545442bafdSRob Clark 
1555442bafdSRob Clark #endif /* __MSM_PERFCNTR_H__ */
156