17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2019-2021 Collabora, Ltd. 37ec681f3Smrg * Author: Antonio Caggiano <antonio.caggiano@collabora.com> 47ec681f3Smrg * Author: Rohan Garg <rohan.garg@collabora.com> 57ec681f3Smrg * Author: Robert Beckett <bob.beckett@collabora.com> 67ec681f3Smrg * 77ec681f3Smrg * SPDX-License-Identifier: MIT 87ec681f3Smrg */ 97ec681f3Smrg 107ec681f3Smrg#include "pan_pps_driver.h" 117ec681f3Smrg 127ec681f3Smrg#include <cstring> 137ec681f3Smrg#include <perfetto.h> 147ec681f3Smrg#include <xf86drm.h> 157ec681f3Smrg 167ec681f3Smrg#include <drm-uapi/panfrost_drm.h> 177ec681f3Smrg#include <perf/pan_perf.h> 187ec681f3Smrg#include <util/macros.h> 197ec681f3Smrg 207ec681f3Smrg#include <pps/pps.h> 217ec681f3Smrg#include <pps/pps_algorithm.h> 227ec681f3Smrg 237ec681f3Smrgnamespace pps 247ec681f3Smrg{ 257ec681f3SmrgPanfrostDriver::PanfrostDriver() 267ec681f3Smrg{ 277ec681f3Smrg} 287ec681f3Smrg 297ec681f3SmrgPanfrostDriver::~PanfrostDriver() 307ec681f3Smrg{ 317ec681f3Smrg} 327ec681f3Smrg 337ec681f3Smrguint64_t PanfrostDriver::get_min_sampling_period_ns() 347ec681f3Smrg{ 357ec681f3Smrg return 1000000; 367ec681f3Smrg} 377ec681f3Smrg 387ec681f3Smrguint32_t find_id_within_group(uint32_t counter_id, const struct panfrost_perf_config *cfg) 397ec681f3Smrg{ 407ec681f3Smrg for (uint32_t cat_id = 0; cat_id < cfg->n_categories; ++cat_id) { 417ec681f3Smrg const struct panfrost_perf_category *cat = &cfg->categories[cat_id]; 427ec681f3Smrg if (counter_id < cat->n_counters) { 437ec681f3Smrg break; 447ec681f3Smrg } 457ec681f3Smrg counter_id -= cat->n_counters; 467ec681f3Smrg } 477ec681f3Smrg 487ec681f3Smrg return counter_id; 497ec681f3Smrg} 507ec681f3Smrg 517ec681f3Smrgstd::pair<std::vector<CounterGroup>, std::vector<Counter>> 527ec681f3SmrgPanfrostDriver::create_available_counters(const PanfrostPerf &perf) 537ec681f3Smrg{ 547ec681f3Smrg std::pair<std::vector<CounterGroup>, std::vector<Counter>> ret; 557ec681f3Smrg auto &[groups, counters] = ret; 567ec681f3Smrg 577ec681f3Smrg size_t cid = 0; 587ec681f3Smrg 597ec681f3Smrg for (uint32_t gid = 0; gid < perf.perf->cfg->n_categories; ++gid) { 607ec681f3Smrg const auto &category = perf.perf->cfg->categories[gid]; 617ec681f3Smrg CounterGroup group = {}; 627ec681f3Smrg group.id = gid; 637ec681f3Smrg group.name = category.name; 647ec681f3Smrg 657ec681f3Smrg for (; cid < category.n_counters; ++cid) { 667ec681f3Smrg Counter counter = {}; 677ec681f3Smrg counter.id = cid; 687ec681f3Smrg counter.group = gid; 697ec681f3Smrg 707ec681f3Smrg uint32_t id_within_group = find_id_within_group(cid, perf.perf->cfg); 717ec681f3Smrg counter.name = category.counters[id_within_group].name; 727ec681f3Smrg 737ec681f3Smrg counter.set_getter([](const Counter &c, const Driver &d) { 747ec681f3Smrg auto &pan_driver = PanfrostDriver::into(d); 757ec681f3Smrg struct panfrost_perf *perf = pan_driver.perf->perf; 767ec681f3Smrg uint32_t id_within_group = find_id_within_group(c.id, perf->cfg); 777ec681f3Smrg const auto counter = &perf->cfg->categories[c.group].counters[id_within_group]; 787ec681f3Smrg return int64_t(panfrost_perf_counter_read(counter, perf)); 797ec681f3Smrg }); 807ec681f3Smrg 817ec681f3Smrg group.counters.push_back(cid); 827ec681f3Smrg 837ec681f3Smrg counters.emplace_back(counter); 847ec681f3Smrg } 857ec681f3Smrg 867ec681f3Smrg groups.push_back(group); 877ec681f3Smrg } 887ec681f3Smrg 897ec681f3Smrg return ret; 907ec681f3Smrg} 917ec681f3Smrg 927ec681f3Smrgbool PanfrostDriver::init_perfcnt() 937ec681f3Smrg{ 947ec681f3Smrg if (!dev) { 957ec681f3Smrg dev = std::make_unique<PanfrostDevice>(drm_device.fd); 967ec681f3Smrg } 977ec681f3Smrg if (!perf) { 987ec681f3Smrg perf = std::make_unique<PanfrostPerf>(*dev); 997ec681f3Smrg } 1007ec681f3Smrg if (groups.empty() && counters.empty()) { 1017ec681f3Smrg std::tie(groups, counters) = create_available_counters(*perf); 1027ec681f3Smrg } 1037ec681f3Smrg return true; 1047ec681f3Smrg} 1057ec681f3Smrg 1067ec681f3Smrgvoid PanfrostDriver::enable_counter(const uint32_t counter_id) 1077ec681f3Smrg{ 1087ec681f3Smrg enabled_counters.push_back(counters[counter_id]); 1097ec681f3Smrg} 1107ec681f3Smrg 1117ec681f3Smrgvoid PanfrostDriver::enable_all_counters() 1127ec681f3Smrg{ 1137ec681f3Smrg enabled_counters.resize(counters.size()); 1147ec681f3Smrg for (size_t i = 0; i < counters.size(); ++i) { 1157ec681f3Smrg enabled_counters[i] = counters[i]; 1167ec681f3Smrg } 1177ec681f3Smrg} 1187ec681f3Smrg 1197ec681f3Smrgvoid PanfrostDriver::enable_perfcnt(const uint64_t /* sampling_period_ns */) 1207ec681f3Smrg{ 1217ec681f3Smrg auto res = perf->enable(); 1227ec681f3Smrg if (!check(res, "Failed to enable performance counters")) { 1237ec681f3Smrg if (res == -ENOSYS) { 1247ec681f3Smrg PERFETTO_FATAL("Please enable unstable ioctls with: modprobe panfrost unstable_ioctls=1"); 1257ec681f3Smrg } 1267ec681f3Smrg PERFETTO_FATAL("Please verify graphics card"); 1277ec681f3Smrg } 1287ec681f3Smrg} 1297ec681f3Smrg 1307ec681f3Smrgbool PanfrostDriver::dump_perfcnt() 1317ec681f3Smrg{ 1327ec681f3Smrg last_dump_ts = perfetto::base::GetBootTimeNs().count(); 1337ec681f3Smrg 1347ec681f3Smrg // Dump performance counters to buffer 1357ec681f3Smrg if (!check(perf->dump(), "Failed to dump performance counters")) { 1367ec681f3Smrg PERFETTO_ELOG("Skipping sample"); 1377ec681f3Smrg return false; 1387ec681f3Smrg } 1397ec681f3Smrg 1407ec681f3Smrg return true; 1417ec681f3Smrg} 1427ec681f3Smrg 1437ec681f3Smrguint64_t PanfrostDriver::next() 1447ec681f3Smrg{ 1457ec681f3Smrg auto ret = last_dump_ts; 1467ec681f3Smrg last_dump_ts = 0; 1477ec681f3Smrg return ret; 1487ec681f3Smrg} 1497ec681f3Smrg 1507ec681f3Smrgvoid PanfrostDriver::disable_perfcnt() 1517ec681f3Smrg{ 1527ec681f3Smrg perf->disable(); 1537ec681f3Smrg perf.reset(); 1547ec681f3Smrg dev.reset(); 1557ec681f3Smrg groups.clear(); 1567ec681f3Smrg counters.clear(); 1577ec681f3Smrg enabled_counters.clear(); 1587ec681f3Smrg} 1597ec681f3Smrg 1607ec681f3Smrg} // namespace pps 161