• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 namespace pps
24 {
PanfrostDriver()25 PanfrostDriver::PanfrostDriver()
26 {
27 }
28 
~PanfrostDriver()29 PanfrostDriver::~PanfrostDriver()
30 {
31 }
32 
get_min_sampling_period_ns()33 uint64_t PanfrostDriver::get_min_sampling_period_ns()
34 {
35    return 1000000;
36 }
37 
find_id_within_group(uint32_t counter_id,const struct panfrost_perf_config * cfg)38 uint32_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 
51 std::pair<std::vector<CounterGroup>, std::vector<Counter>>
create_available_counters(const PanfrostPerf & perf)52 PanfrostDriver::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 
init_perfcnt()92 bool 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 
enable_counter(const uint32_t counter_id)106 void PanfrostDriver::enable_counter(const uint32_t counter_id)
107 {
108    enabled_counters.push_back(counters[counter_id]);
109 }
110 
enable_all_counters()111 void 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 
enable_perfcnt(const uint64_t)119 void 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 
dump_perfcnt()130 bool 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 
next()143 uint64_t PanfrostDriver::next()
144 {
145    auto ret = last_dump_ts;
146    last_dump_ts = 0;
147    return ret;
148 }
149 
disable_perfcnt()150 void 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