pan_pps_driver.cc revision 7ec681f3
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 23namespace pps 24{ 25PanfrostDriver::PanfrostDriver() 26{ 27} 28 29PanfrostDriver::~PanfrostDriver() 30{ 31} 32 33uint64_t PanfrostDriver::get_min_sampling_period_ns() 34{ 35 return 1000000; 36} 37 38uint32_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 51std::pair<std::vector<CounterGroup>, std::vector<Counter>> 52PanfrostDriver::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 92bool 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 106void PanfrostDriver::enable_counter(const uint32_t counter_id) 107{ 108 enabled_counters.push_back(counters[counter_id]); 109} 110 111void 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 119void 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 130bool 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 143uint64_t PanfrostDriver::next() 144{ 145 auto ret = last_dump_ts; 146 last_dump_ts = 0; 147 return ret; 148} 149 150void 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