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