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