From 14614060b8028f9ab4809f0b0e110a23980ecd14 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 27 Aug 2013 12:24:18 +0100 Subject: overlay: Read frequency from perf Signed-off-by: Chris Wilson --- overlay/gpu-freq.c | 105 ++++++++++++++++++++++++++++++++++++++++++----------- overlay/gpu-freq.h | 8 ++++ 2 files changed, 91 insertions(+), 22 deletions(-) (limited to 'overlay') diff --git a/overlay/gpu-freq.c b/overlay/gpu-freq.c index 0a400be6..f6bc67a1 100644 --- a/overlay/gpu-freq.c +++ b/overlay/gpu-freq.c @@ -30,6 +30,38 @@ #include "gpu-freq.h" #include "debugfs.h" +#include "perf.h" + +static int perf_i915_open(int config, int group) +{ + struct perf_event_attr attr; + + memset(&attr, 0, sizeof (attr)); + + attr.type = i915_type_id(); + if (attr.type == 0) + return -ENOENT; + attr.config = config; + + attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED; + if (group == -1) + attr.read_format |= PERF_FORMAT_GROUP; + + return perf_event_open(&attr, -1, 0, group, 0); +} + +static int perf_open(void) +{ + int fd; + + fd = perf_i915_open(I915_PERF_ACTUAL_FREQUENCY, -1); + if (perf_i915_open(I915_PERF_REQUESTED_FREQUENCY, fd) < 0) { + close(fd); + fd = -1; + } + + return fd; +} int gpu_freq_init(struct gpu_freq *gf) { @@ -38,6 +70,8 @@ int gpu_freq_init(struct gpu_freq *gf) memset(gf, 0, sizeof(*gf)); + gf->fd = perf_open(); + sprintf(buf, "%s/i915_cur_delayinfo", debugfs_dri_path); fd = open(buf, 0); if (fd < 0) @@ -79,31 +113,58 @@ err: int gpu_freq_update(struct gpu_freq *gf) { - char buf[4096], *s; - int fd, len = -1; - if (gf->error) return gf->error; - sprintf(buf, "%s/i915_cur_delayinfo", debugfs_dri_path); - fd = open(buf, 0); - if (fd < 0) - return gf->error = errno; - - len = read(fd, buf, sizeof(buf)-1); - close(fd); - if (len < 0) - return gf->error = EIO; - - buf[len] = '\0'; - - s = strstr(buf, "RPNSWREQ:"); - if (s) - sscanf(s, "RPNSWREQ: %dMHz", &gf->request); - - s = strstr(buf, "CAGF:"); - if (s) - sscanf(s, "CAGF: %dMHz", &gf->current); + if (gf->fd < 0) { + char buf[4096], *s; + int fd, len = -1; + + sprintf(buf, "%s/i915_cur_delayinfo", debugfs_dri_path); + fd = open(buf, 0); + if (fd < 0) + return gf->error = errno; + + len = read(fd, buf, sizeof(buf)-1); + close(fd); + if (len < 0) + return gf->error = EIO; + + buf[len] = '\0'; + + s = strstr(buf, "RPNSWREQ:"); + if (s) + sscanf(s, "RPNSWREQ: %dMHz", &gf->request); + + s = strstr(buf, "CAGF:"); + if (s) + sscanf(s, "CAGF: %dMHz", &gf->current); + } else { + struct gpu_freq_stat *s = &gf->stat[gf->count++&1]; + struct gpu_freq_stat *d = &gf->stat[gf->count&1]; + uint64_t data[4], d_time; + int len; + + len = read(gf->fd, data, sizeof(data)); + if (len < 0) + return gf->error = errno; + + s->timestamp = data[1]; + s->act = data[2]; + s->req = data[3]; + + if (gf->count == 1) + return EAGAIN; + + d_time = s->timestamp - d->timestamp; + if (d_time == 0) { + gf->count--; + return EAGAIN; + } + + gf->current = (s->act - d->act) / d_time; + gf->request = (s->req - d->req) / d_time; + } return 0; } diff --git a/overlay/gpu-freq.h b/overlay/gpu-freq.h index d78aa1bb..cdd2bb6c 100644 --- a/overlay/gpu-freq.h +++ b/overlay/gpu-freq.h @@ -25,7 +25,15 @@ #ifndef GPU_FREQ_H #define GPU_FREQ_H +#include + struct gpu_freq { + struct gpu_freq_stat { + uint64_t act, req; + uint64_t timestamp; + } stat[2]; + int fd; + int count; int min, max; int rpn, rp1, rp0; int request; -- cgit v1.2.3