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