xref: /aosp_15_r20/external/mesa3d/src/panfrost/ds/pan_pps_driver.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2019-2021 Collabora, Ltd.
3  * Author: Antonio Caggiano <[email protected]>
4  * Author: Rohan Garg <[email protected]>
5  * Author: Robert Beckett <[email protected]>
6  *
7  * SPDX-License-Identifier: MIT
8  */
9 
10 #include "pan_pps_driver.h"
11 
12 #include <cstring>
13 #include <perfetto.h>
14 #include <xf86drm.h>
15 
16 #include <drm-uapi/panfrost_drm.h>
17 #include <perf/pan_perf.h>
18 #include <util/macros.h>
19 
20 #include <pps/pps.h>
21 #include <pps/pps_algorithm.h>
22 
23 namespace pps {
PanfrostDriver()24 PanfrostDriver::PanfrostDriver()
25 {
26 }
27 
~PanfrostDriver()28 PanfrostDriver::~PanfrostDriver()
29 {
30 }
31 
32 uint64_t
get_min_sampling_period_ns()33 PanfrostDriver::get_min_sampling_period_ns()
34 {
35    return 1000000;
36 }
37 
38 uint32_t
find_id_within_group(uint32_t counter_id,const struct panfrost_perf_config * cfg)39 find_id_within_group(uint32_t counter_id,
40                      const struct panfrost_perf_config *cfg)
41 {
42    for (uint32_t cat_id = 0; cat_id < cfg->n_categories; ++cat_id) {
43       const struct panfrost_perf_category *cat = &cfg->categories[cat_id];
44       if (counter_id < cat->n_counters) {
45          break;
46       }
47       counter_id -= cat->n_counters;
48    }
49 
50    return counter_id;
51 }
52 
53 std::pair<std::vector<CounterGroup>, std::vector<Counter>>
create_available_counters(const PanfrostPerf & perf)54 PanfrostDriver::create_available_counters(const PanfrostPerf &perf)
55 {
56    std::pair<std::vector<CounterGroup>, std::vector<Counter>> ret;
57    auto &[groups, counters] = ret;
58 
59    size_t cid = 0;
60 
61    for (uint32_t gid = 0; gid < perf.perf->cfg->n_categories; ++gid) {
62       const auto &category = perf.perf->cfg->categories[gid];
63       CounterGroup group = {};
64       group.id = gid;
65       group.name = category.name;
66 
67       for (; cid < category.n_counters; ++cid) {
68          Counter counter = {};
69          counter.id = cid;
70          counter.group = gid;
71 
72          uint32_t id_within_group = find_id_within_group(cid, perf.perf->cfg);
73          counter.name = category.counters[id_within_group].name;
74 
75          counter.set_getter([](const Counter &c, const Driver &d) {
76             auto &pan_driver = PanfrostDriver::into(d);
77             struct panfrost_perf *perf = pan_driver.perf->perf;
78             uint32_t id_within_group = find_id_within_group(c.id, perf->cfg);
79             const auto counter =
80                &perf->cfg->categories[c.group].counters[id_within_group];
81             return int64_t(panfrost_perf_counter_read(counter, perf));
82          });
83 
84          group.counters.push_back(cid);
85 
86          counters.emplace_back(counter);
87       }
88 
89       groups.push_back(group);
90    }
91 
92    return ret;
93 }
94 
95 bool
init_perfcnt()96 PanfrostDriver::init_perfcnt()
97 {
98    if (!dev) {
99       dev = std::make_unique<PanfrostDevice>(drm_device.fd);
100    }
101    if (!perf) {
102       perf = std::make_unique<PanfrostPerf>(*dev);
103    }
104    if (groups.empty() && counters.empty()) {
105       std::tie(groups, counters) = create_available_counters(*perf);
106    }
107    return true;
108 }
109 
110 void
enable_counter(const uint32_t counter_id)111 PanfrostDriver::enable_counter(const uint32_t counter_id)
112 {
113    enabled_counters.push_back(counters[counter_id]);
114 }
115 
116 void
enable_all_counters()117 PanfrostDriver::enable_all_counters()
118 {
119    enabled_counters.resize(counters.size());
120    for (size_t i = 0; i < counters.size(); ++i) {
121       enabled_counters[i] = counters[i];
122    }
123 }
124 
125 void
enable_perfcnt(const uint64_t)126 PanfrostDriver::enable_perfcnt(const uint64_t /* sampling_period_ns */)
127 {
128    auto res = perf->enable();
129    if (!check(res, "Failed to enable performance counters")) {
130       if (res == -ENOSYS) {
131          PERFETTO_FATAL(
132             "Please enable unstable ioctls with: modprobe panfrost unstable_ioctls=1");
133       }
134       PERFETTO_FATAL("Please verify graphics card");
135    }
136 }
137 
138 bool
dump_perfcnt()139 PanfrostDriver::dump_perfcnt()
140 {
141    last_dump_ts = perfetto::base::GetBootTimeNs().count();
142 
143    // Dump performance counters to buffer
144    if (!check(perf->dump(), "Failed to dump performance counters")) {
145       PERFETTO_ELOG("Skipping sample");
146       return false;
147    }
148 
149    return true;
150 }
151 
152 uint64_t
next()153 PanfrostDriver::next()
154 {
155    auto ret = last_dump_ts;
156    last_dump_ts = 0;
157    return ret;
158 }
159 
160 void
disable_perfcnt()161 PanfrostDriver::disable_perfcnt()
162 {
163    perf->disable();
164    perf.reset();
165    dev.reset();
166    groups.clear();
167    counters.clear();
168    enabled_counters.clear();
169 }
170 
171 uint32_t
gpu_clock_id() const172 PanfrostDriver::gpu_clock_id() const
173 {
174    return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
175 }
176 
177 uint64_t
gpu_timestamp() const178 PanfrostDriver::gpu_timestamp() const
179 {
180    return perfetto::base::GetBootTimeNs().count();
181 }
182 
183 bool
cpu_gpu_timestamp(uint64_t &,uint64_t &) const184 PanfrostDriver::cpu_gpu_timestamp(uint64_t &, uint64_t &) const
185 {
186    /* Not supported */
187    return false;
188 }
189 
190 } // namespace pps
191