// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com>
*/
/* For profiling, userspace can: * * tail -f /sys/kernel/debug/dri/<minor>/gpu * * This will enable performance counters/profiling to track the busy time * and any gpu specific performance counters that are supported.
*/
/* wait for next sample time: */ staticint wait_sample(struct msm_perf_state *perf)
{ unsignedlong start_jiffies = jiffies;
if (time_after(perf->next_jiffies, start_jiffies)) { unsignedlong remaining_jiffies =
perf->next_jiffies - start_jiffies; int ret = schedule_timeout_interruptible(remaining_jiffies); if (ret > 0) { /* interrupted */ return -ERESTARTSYS;
}
}
perf->next_jiffies += SAMPLE_TIME; return 0;
}
staticint refill_buf(struct msm_perf_state *perf)
{ struct msm_drm_private *priv = perf->dev->dev_private; struct msm_gpu *gpu = priv->gpu; char *ptr = perf->buf; int rem = sizeof(perf->buf); int i, n;
if ((perf->cnt++ % 32) == 0) { /* Header line: */
n = snprintf(ptr, rem, "%%BUSY");
ptr += n;
rem -= n;
for (i = 0; i < gpu->num_perfcntrs; i++) { conststruct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
n = snprintf(ptr, rem, "\t%s", perfcntr->name);
ptr += n;
rem -= n;
}
} else { /* Sample line: */
uint32_t activetime = 0, totaltime = 0;
uint32_t cntrs[5];
uint32_t val; int ret;
/* sleep until next sample time: */
ret = wait_sample(perf); if (ret) return ret;
ret = msm_gpu_perfcntr_sample(gpu, &activetime, &totaltime,
ARRAY_SIZE(cntrs), cntrs); if (ret < 0) return ret;
val = totaltime ? 1000 * activetime / totaltime : 0;
n = snprintf(ptr, rem, "%3d.%d%%", val / 10, val % 10);
ptr += n;
rem -= n;
for (i = 0; i < ret; i++) { /* cycle counters (I think).. convert to MHz.. */
val = cntrs[i] / 10000;
n = snprintf(ptr, rem, "\t%5d.%02d",
val / 100, val % 100);
ptr += n;
rem -= n;
}
}
n = snprintf(ptr, rem, "\n");
ptr += n;
rem -= n;
perf->bufpos = 0;
perf->buftot = ptr - perf->buf;
return 0;
}
static ssize_t perf_read(struct file *file, char __user *buf,
size_t sz, loff_t *ppos)
{ struct msm_perf_state *perf = file->private_data; int n = 0, ret = 0;
mutex_lock(&perf->read_lock);
if (perf->bufpos >= perf->buftot) {
ret = refill_buf(perf); if (ret) goto out;
}
n = min((int)sz, perf->buftot - perf->bufpos); if (copy_to_user(buf, &perf->buf[perf->bufpos], n)) {
ret = -EFAULT; goto out;
}
perf->bufpos += n;
*ppos += n;
out:
mutex_unlock(&perf->read_lock); if (ret) return ret; return n;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.