summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_perfcntr.h
blob: 0feeb81c531fe579ee04003ebf1be8944feb6c7b (plain) (blame)
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
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
 */

#ifndef __MSM_PERFCNTR_H__
#define __MSM_PERFCNTR_H__

#include "linux/array_size.h"
#include "linux/circ_buf.h"
#include "linux/hrtimer.h"
#include "linux/kthread.h"
#include "linux/wait.h"
#include "linux/workqueue.h"

#include "adreno_common.xml.h"

/*
 * This is a subset of the tables used by mesa.  We don't need to
 * enumerate the countables on the kernel side.
 */

/* Describes a single counter: */
struct msm_perfcntr_counter {
	/* offset of the SELect register to choose what to count: */
	unsigned select_reg;
	/* additional SEL regs to enable slice counters (gen8+) */
	unsigned slice_select_regs[2];
	/* offset of the lo/hi 32b to read current counter value: */
	unsigned counter_reg_lo;
	unsigned counter_reg_hi;
	/* TODO some counters have enable/clear registers */
};

/* Describes an entire counter group: */
struct msm_perfcntr_group {
	const char *name;
	enum adreno_pipe pipe;
	unsigned num_counters;
	const struct msm_perfcntr_counter *counters;
};

/**
 * struct msm_perfcntr_stream - state for a single open stream fd
 */
struct msm_perfcntr_stream {
	/** @gpu: Back-link to the GPU */
	struct msm_gpu *gpu;

	/** @sample_timer: Timer to sample counters */
	struct hrtimer sample_timer;

	/** @poll_wq: Wait queue for waiting for OA data to be available */
	wait_queue_head_t poll_wq;

	/** @sample_period_ns: Sampling period */
	uint64_t sample_period_ns;

	/** @nr_groups: # of counter groups with enabled counters */
	uint32_t nr_groups;

	/** @seqno: counter for collected samples */
	uint32_t seqno;

	/** @sel_fence: Fence for SEL reg programming  */
	uint32_t sel_fence;

	/**
	 * @sel_work: Worker for SEL reg programming
	 *
	 * Initial SEL reg programming (as opposed to restoring the SEL
	 * regs on runpm resume) must run on the same ordered wq as is
	 * used by drm_sched, to serialize it with GEM_SUBMITs written
	 * into the same ringbuffer.
	 */
	struct work_struct sel_work;

	/**
	 * @sample_work: Worker for collecting samples
	 */
	struct kthread_work sample_work;

	/**
	 * @read_lock:
	 *
	 * Fifo access is synchronied on the producer side by virtue
	 * of there being a single timer collecting samples and writing
	 * into the fifo.  It is protected on the consumer side by
	 * @read_lock.
	 */
	struct mutex read_lock;

	/**
	 * @group_idx: array of nr_groups
	 *
	 * Maps the order of groups in PERFCNTR_CONFIG ioctl to group idx,
	 * so that results in the results stream can be ordered to match
	 * the ioctl call that setup the stream
	 */
	uint32_t *group_idx;

	/** @fifo: circular buffer for samples */
	struct circ_buf fifo;

	/** @fifo_size: circular buffer size */
	size_t fifo_size;

	/** @period_size: size of data for single sampling period */
	size_t period_size;
};

uint32_t msm_perfcntr_group_idx(const struct msm_perfcntr_stream *stream, uint32_t n);
uint32_t msm_perfcntr_counter_base(const struct msm_perfcntr_stream *stream, uint32_t group_idx);

/**
 * struct msm_perfcntr_context_state - per-msm_context counter state
 *
 * A given counter can either be unused, reserved for global counter
 * collection exclusively, or reserved for local per-context counter
 * collection inclusively.  Multiple contexts can reserve the same
 * counter, since SEL reg programming and counter begin/end sampling
 * happen locally (within a single GEM_SUBMIT ioctl).
 */
struct msm_perfcntr_context_state {
	/** @dummy: Some compilers dislike structs with only a flex array */
	unsigned dummy;

	/**
	 * @reserved_counters:
	 *
	 * The number of reserved counters indexed by perfcntr group.
	 */
	unsigned reserved_counters[];
};

extern const struct msm_perfcntr_group a6xx_perfcntr_groups[];
extern const unsigned a6xx_num_perfcntr_groups;

extern const struct msm_perfcntr_group a7xx_perfcntr_groups[];
extern const unsigned a7xx_num_perfcntr_groups;

extern const struct msm_perfcntr_group a8xx_perfcntr_groups[];
extern const unsigned a8xx_num_perfcntr_groups;

#define GROUP(_name, _pipe, _counters, _countables) {                          \
      .name = _name,                                                           \
      .pipe = _pipe,                                                           \
      .num_counters = ARRAY_SIZE(_counters),                                   \
      .counters = _counters,                                                   \
   }

#define fd_perfcntr_counter msm_perfcntr_counter
#define fd_perfcntr_group   msm_perfcntr_group

#endif /* __MSM_PERFCNTR_H__ */