pan/pps: Delegate more tasks to PanfrostPerf

This makes it so that everything that uses the pan_perf C lib is
hidden inside PanfrostPerf instead of being used directly from the
pps driver.

Co-Authored-by: Lukas Zapolskas <lukas.zapolskas@arm.com>
This commit is contained in:
Christoph Pillmayer 2026-03-20 12:47:19 +01:00
parent 8141fd7342
commit 51992c8556
3 changed files with 137 additions and 66 deletions

View file

@ -33,46 +33,13 @@ PanfrostDriver::~PanfrostDriver()
uint64_t
PanfrostDriver::get_min_sampling_period_ns()
{
return 1000000;
return perf->get_min_sampling_period_ns();
}
std::pair<std::vector<CounterGroup>, std::vector<Counter>>
PanfrostDriver::create_available_counters(const PanfrostPerf &perf)
{
std::pair<std::vector<CounterGroup>, std::vector<Counter>> ret;
auto &[groups, counters] = ret;
size_t cid = 0;
for (uint32_t gid = 0; gid < perf.perf->cfg->n_categories; ++gid) {
const auto &category = perf.perf->cfg->categories[gid];
CounterGroup group = {};
group.id = gid;
group.name = category.name;
for (size_t id = 0; id < category.n_counters; ++id) {
Counter counter = {};
counter.id = cid;
counter.group = gid;
counter.name = category.counters[id].name;
counter.set_getter([=](const Counter &c, const Driver &d) {
auto &pan_driver = PanfrostDriver::into(d);
struct pan_perf *perf = pan_driver.perf->perf;
const auto counter = &perf->cfg->categories[gid].counters[id];
return int64_t(pan_perf_counter_read(counter, perf));
});
group.counters.push_back(cid++);
counters.emplace_back(counter);
}
groups.push_back(group);
}
return ret;
return perf.create_available_counters();
}
bool
@ -81,9 +48,12 @@ PanfrostDriver::init_perfcnt()
if (!dev) {
dev = std::make_unique<PanfrostDevice>(drm_device.fd);
}
if (!perf) {
perf = std::make_unique<PanfrostPerf>(*dev);
}
perf->init_perfcnt(drm_device.fd);
if (groups.empty() && counters.empty()) {
std::tie(groups, counters) = create_available_counters(*perf);
}
@ -106,9 +76,9 @@ PanfrostDriver::enable_all_counters()
}
void
PanfrostDriver::enable_perfcnt(const uint64_t /* sampling_period_ns */)
PanfrostDriver::enable_perfcnt(const uint64_t sampling_period_ns)
{
auto res = perf->enable();
auto res = perf->enable_perfcnt(sampling_period_ns);
if (!check(res, "Failed to enable performance counters")) {
if (res == -ENOSYS) {
PERFETTO_FATAL(
@ -121,10 +91,8 @@ PanfrostDriver::enable_perfcnt(const uint64_t /* sampling_period_ns */)
bool
PanfrostDriver::dump_perfcnt()
{
last_dump_ts = perfetto::base::GetBootTimeNs().count();
// Dump performance counters to buffer
if (!check(perf->dump(), "Failed to dump performance counters")) {
if (!check(perf->dump_perfcnt(), "Failed to dump performance counters")) {
PERFETTO_ELOG("Skipping sample");
return false;
}
@ -135,15 +103,13 @@ PanfrostDriver::dump_perfcnt()
uint64_t
PanfrostDriver::next()
{
auto ret = last_dump_ts;
last_dump_ts = 0;
return ret;
return perf->next();
}
void
PanfrostDriver::disable_perfcnt()
{
perf->disable();
perf->disable_perfcnt();
perf.reset();
dev.reset();
groups.clear();
@ -154,20 +120,19 @@ PanfrostDriver::disable_perfcnt()
uint32_t
PanfrostDriver::gpu_clock_id() const
{
return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
return perf->gpu_clock_id();
}
uint64_t
PanfrostDriver::gpu_timestamp() const
{
return perfetto::base::GetBootTimeNs().count();
return perf->gpu_timestamp();
}
bool
PanfrostDriver::cpu_gpu_timestamp(uint64_t &, uint64_t &) const
PanfrostDriver::cpu_gpu_timestamp(uint64_t &cpu_timestamp, uint64_t &gpu_timestamp) const
{
/* Not supported */
return false;
return perf->cpu_gpu_timestamp(cpu_timestamp, gpu_timestamp);
}
} // namespace pps

View file

@ -4,6 +4,7 @@
*/
#include "pan_pps_perf.h"
#include "pan_pps_driver.h"
#include <lib/kmod/pan_kmod.h>
#include <perf/pan_perf.h>
@ -12,14 +13,12 @@
#include <util/ralloc.h>
namespace pps {
PanfrostPerf::PanfrostPerf(const PanfrostDevice &dev)
: perf{reinterpret_cast<struct pan_perf *>(
rzalloc(nullptr, struct pan_perf))}
{
perf = reinterpret_cast<struct pan_perf *>(
rzalloc(nullptr, struct pan_perf));
assert(perf);
assert(dev.fd >= 0);
pan_perf_init(perf, dev.fd);
}
PanfrostPerf::~PanfrostPerf()
@ -31,7 +30,7 @@ PanfrostPerf::~PanfrostPerf()
}
}
PanfrostPerf::PanfrostPerf(PanfrostPerf &&o): perf{o.perf}
PanfrostPerf::PanfrostPerf(PanfrostPerf &&o): perf(o.perf)
{
o.perf = nullptr;
}
@ -43,25 +42,116 @@ PanfrostPerf::operator=(PanfrostPerf &&o)
return *this;
}
bool
PanfrostPerf::init_perfcnt(int fd)
{
pan_perf_init(perf, fd);
return perf != NULL;
}
int
PanfrostPerf::enable() const
PanfrostPerf::enable_perfcnt(uint64_t /* sampling_period_ns */)
{
assert(perf);
return pan_perf_enable(perf);
}
void
PanfrostPerf::disable() const
PanfrostPerf::disable_perfcnt()
{
assert(perf);
pan_perf_disable(perf);
}
int
PanfrostPerf::dump() const
bool
PanfrostPerf::dump_perfcnt()
{
assert(perf);
return pan_perf_dump(perf);
last_dump_ts = perfetto::base::GetBootTimeNs().count();
int ret = pan_perf_dump(perf);
return !!(ret >= 0);
}
uint64_t
PanfrostPerf::get_min_sampling_period_ns()
{
return 1000000;
}
void *
PanfrostPerf::get_subinstance() {
return perf;
}
std::pair<std::vector<CounterGroup>, std::vector<Counter>>
PanfrostPerf::create_available_counters() const
{
std::pair<std::vector<CounterGroup>, std::vector<Counter>> ret;
auto &[groups, counters] = ret;
size_t cid = 0;
for (uint32_t gid = 0; gid < perf->cfg->n_categories; ++gid) {
const auto &category = perf->cfg->categories[gid];
CounterGroup group = {};
group.id = gid;
group.name = category.name;
for (size_t id = 0; cid < category.n_counters; ++cid) {
Counter counter = {};
counter.id = cid;
counter.group = gid;
counter.name = category.counters[id].name;
counter.set_getter([=](const Counter &c, const Driver &d) {
auto &pan_driver = PanfrostDriver::into(d);
struct pan_perf *perf = static_cast<struct pan_perf *>(
pan_driver.perf->get_subinstance());
const auto counter =
&perf->cfg->categories[gid].counters[id];
return int64_t(pan_perf_counter_read(counter, perf));
});
group.counters.push_back(cid++);
counters.emplace_back(counter);
}
groups.push_back(group);
}
return ret;
}
uint64_t
PanfrostPerf::next()
{
auto ret = last_dump_ts;
last_dump_ts = 0;
return ret;
}
uint32_t
PanfrostPerf::gpu_clock_id() const
{
return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
}
uint64_t
PanfrostPerf::gpu_timestamp() const
{
return perfetto::base::GetBootTimeNs().count();
}
bool
PanfrostPerf::cpu_gpu_timestamp(uint64_t &, uint64_t &) const
{
/* Not supported */
return false;
}
} // namespace pps

View file

@ -5,6 +5,12 @@
#pragma once
#include <cstdint>
#include <vector>
#include <utility>
#include <pps/pps.h>
#include <pps/pps_counter.h>
struct pan_perf;
namespace pps {
@ -27,17 +33,27 @@ class PanfrostPerf {
PanfrostPerf(const PanfrostDevice &dev);
~PanfrostPerf();
PanfrostPerf(const PanfrostPerf &) = delete;
PanfrostPerf &operator=(const PanfrostPerf &) = delete;
PanfrostPerf(PanfrostPerf &&o);
PanfrostPerf &operator=(PanfrostPerf &&o);
PanfrostPerf(PanfrostPerf &&);
PanfrostPerf &operator=(PanfrostPerf &&);
std::pair<std::vector<CounterGroup>, std::vector<Counter>>
create_available_counters() const;
int enable() const;
void disable() const;
int dump() const;
uint64_t get_min_sampling_period_ns();
bool init_perfcnt(int fd);
int enable_perfcnt(uint64_t sampling_period_ns);
void disable_perfcnt();
bool dump_perfcnt();
uint64_t next();
uint32_t gpu_clock_id() const;
uint64_t gpu_timestamp() const;
bool cpu_gpu_timestamp(uint64_t &cpu_timestamp,
uint64_t &gpu_timestamp) const;
void *get_subinstance();
private:
struct pan_perf *perf = nullptr;
uint64_t last_dump_ts = 0;
};
} // namespace pps