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