pan/kmod: Implement panfrost kmod perf counter methods

This is mostly a copy of the logic from pan_perf.c and hooking it up
to the kmod api.
This commit is contained in:
Christoph Pillmayer 2026-03-18 10:39:08 +01:00
parent dcc0dc10d7
commit 901dd8dc6c

View file

@ -42,6 +42,10 @@ struct panfrost_kmod_bo {
uint64_t offset;
};
struct panfrost_kmod_perf_session {
struct pan_kmod_perf_session base;
};
/* Abstraction over the raw drm_panfrost_get_param ioctl for fetching
* information about devices.
*/
@ -607,6 +611,106 @@ panfrost_kmod_bo_label(struct pan_kmod_dev *dev, struct pan_kmod_bo *bo, const c
mesa_loge("DRM_IOCTL_PANFROST_SET_LABEL_BO failed (err=%d)", errno);
}
static inline struct pan_kmod_perf_session *
panfrost_kmod_perf_init(struct pan_kmod_dev *dev)
{
UNUSED struct panfrost_kmod_dev *panfrost_dev =
container_of(dev, struct panfrost_kmod_dev, base);
struct panfrost_kmod_perf_session *sess =
pan_kmod_dev_alloc(dev, sizeof(*sess));
if (!sess) {
mesa_loge("failed to allocate a panfrost_kmod_perf_session object");
return NULL;
}
sess->base.dev = dev;
struct pan_kmod_perf_buffer_layout layout;
pan_kmod_perf_query_layout(&sess->base, &layout);
uint32_t n_counters = 0;
for (uint32_t cat = 0; cat < PAN_KMOD_PERF_CAT_COUNT; ++cat)
n_counters += layout.category[cat].n_blocks * layout.counters_per_category;
uint32_t* counter_values = pan_kmod_dev_alloc(dev, sizeof(uint32_t) * n_counters);
sess->base.data = counter_values;
sess->base.data_ts_supported = false;
mesa_logd("perf session created");
return &(sess->base);
}
static int
panfrost_kmod_perf_query(struct pan_kmod_perf_session *session, uint32_t enable)
{
struct drm_panfrost_perfcnt_enable perfcnt_enable = {enable, 0};
return pan_kmod_ioctl(session->dev->fd, DRM_IOCTL_PANFROST_PERFCNT_ENABLE,
&perfcnt_enable);
}
static int
panfrost_kmod_perf_enable(struct pan_kmod_perf_session *session)
{
return panfrost_kmod_perf_query(session, 1 /* enable */);
}
static int
panfrost_kmod_perf_disable(struct pan_kmod_perf_session *session)
{
return panfrost_kmod_perf_query(session, 0 /* disable */);
}
static int
panfrost_kmod_perf_dump(struct pan_kmod_perf_session *session)
{
struct drm_panfrost_perfcnt_dump perfcnt_dump = {
(uint64_t)(uintptr_t)session->data};
return pan_kmod_ioctl(session->dev->fd, DRM_IOCTL_PANFROST_PERFCNT_DUMP,
&perfcnt_dump);
}
static void
panfrost_kmod_perf_query_layout(const struct pan_kmod_perf_session *session,
struct pan_kmod_perf_buffer_layout *layout)
{
/* Generally counter blocks are laid out in the following order:
* Job manager, tiler, one or more L2 caches, and one or more shader cores.
*/
unsigned l2_slices = pan_query_l2_slices(&session->dev->props);
unsigned core_id_range;
pan_query_core_count(&session->dev->props, &core_id_range);
/* On all Bifrost architectures this is 64. */
const unsigned counters_per_cat = 64;
layout->counters_per_category = counters_per_cat;
layout->counter_stride = sizeof(uint32_t);
layout->block_stride = counters_per_cat * sizeof(uint32_t);
/* Setup the layout */
layout->category[PAN_KMOD_PERF_CAT_FRONTEND].n_blocks = 1;
layout->category[PAN_KMOD_PERF_CAT_TILER].n_blocks = 1;
layout->category[PAN_KMOD_PERF_CAT_MEMSYS].n_blocks = l2_slices;
layout->category[PAN_KMOD_PERF_CAT_SHADER].n_blocks = core_id_range;
layout->category[0].offset = 0;
for (unsigned cat_idx = 1; cat_idx < PAN_KMOD_PERF_CAT_COUNT; ++cat_idx) {
layout->category[cat_idx].offset =
layout->category[cat_idx - 1].offset +
layout->category[cat_idx - 1].n_blocks * counters_per_cat;
}
}
static void
panfrost_kmod_perf_destroy(struct pan_kmod_perf_session *session)
{
if (session->data)
pan_kmod_dev_free(session->dev, session->data);
pan_kmod_dev_free(session->dev, session);
mesa_logd("perf session destroyed");
}
const struct pan_kmod_ops panfrost_kmod_ops = {
.dev_create = panfrost_kmod_dev_create,
.dev_destroy = panfrost_kmod_dev_destroy,
@ -624,4 +728,10 @@ const struct pan_kmod_ops panfrost_kmod_ops = {
.vm_bind = panfrost_kmod_vm_bind,
.query_timestamp = panfrost_kmod_query_timestamp,
.bo_set_label = panfrost_kmod_bo_label,
.perf_create = panfrost_kmod_perf_init,
.perf_enable = panfrost_kmod_perf_enable,
.perf_disable = panfrost_kmod_perf_disable,
.perf_dump = panfrost_kmod_perf_dump,
.perf_query_layout = panfrost_kmod_perf_query_layout,
.perf_destroy = panfrost_kmod_perf_destroy,
};