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