summaryrefslogtreecommitdiff
path: root/overlay
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-08-27 12:24:18 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-08-27 12:31:13 +0100
commitd58aed18ee77b5e8afa7c9eda389786db6ab1818 (patch)
tree5fb6ae1760e4f015e18b4e06bd52ebd4ca95a1a5 /overlay
parent14614060b8028f9ab4809f0b0e110a23980ecd14 (diff)
overlay: Read interrupts from perf
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'overlay')
-rw-r--r--overlay/gem-interrupts.c78
-rw-r--r--overlay/gem-interrupts.h1
2 files changed, 56 insertions, 23 deletions
diff --git a/overlay/gem-interrupts.c b/overlay/gem-interrupts.c
index 7377ee71..15dc7919 100644
--- a/overlay/gem-interrupts.c
+++ b/overlay/gem-interrupts.c
@@ -32,50 +32,82 @@
#include "gem-interrupts.h"
#include "debugfs.h"
+#include "perf.h"
-int gem_interrupts_init(struct gem_interrupts *irqs)
+static int perf_open(void)
{
- char buf[1024];
- struct stat st;
+ struct perf_event_attr attr;
+ memset(&attr, 0, sizeof (attr));
- memset(irqs, 0, sizeof(*irqs));
+ attr.type = i915_type_id();
+ if (attr.type == 0)
+ return -ENOENT;
+ attr.config = I915_PERF_INTERRUPTS;
+
+ return perf_event_open(&attr, -1, 0, -1, 0);
+}
+
+static int debugfs_open(void)
+{
+ char buf[1024];
+ struct stat st;
sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path);
if (stat(buf, &st))
- return irqs->error = errno;
+ return errno;
return 0;
}
+int gem_interrupts_init(struct gem_interrupts *irqs)
+{
+ memset(irqs, 0, sizeof(*irqs));
+
+ irqs->fd = perf_open();
+ if (irqs->fd < 0)
+ irqs->error = debugfs_open();
+
+ return irqs->error;
+}
+
int gem_interrupts_update(struct gem_interrupts *irqs)
{
- char buf[8192], *b;
- int fd, len;
+ uint64_t val;
+ int update;
if (irqs->error)
return irqs->error;
- sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path);
- fd = open(buf, 0);
- if (fd < 0)
- return irqs->error = errno;
- len = read(fd, buf, sizeof(buf)-1);
- close(fd);
+ if (irqs->fd < 0) {
+ char buf[8192], *b;
+ int fd, len;
+
+ sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path);
+ fd = open(buf, 0);
+ if (fd < 0)
+ return irqs->error = errno;
+ len = read(fd, buf, sizeof(buf)-1);
+ close(fd);
- if (len < 0)
- return irqs->error = errno;
+ if (len < 0)
+ return irqs->error = errno;
- buf[len] = '\0';
+ buf[len] = '\0';
- b = strstr(buf, "Interrupts received:");
- if (b == NULL)
- return irqs->error = ENOENT;
+ b = strstr(buf, "Interrupts received:");
+ if (b == NULL)
+ return irqs->error = ENOENT;
- fd = irqs->last_count == 0;
+ val = strtoull(b + sizeof("Interrupts received:"), 0, 0);
+ } else {
+ if (read(irqs->fd, &val, sizeof(val)) < 0)
+ return irqs->error = errno;
+ }
+
+ update = irqs->last_count == 0;
irqs->last_count = irqs->count;
- irqs->count = strtoull(b + sizeof("Interrupts received:"), 0, 0);
+ irqs->count = val;
irqs->delta = irqs->count - irqs->last_count;
-
- return fd ? EAGAIN : 0;
+ return update ? EAGAIN : 0;
}
diff --git a/overlay/gem-interrupts.h b/overlay/gem-interrupts.h
index e9dbc4a9..a818ec8b 100644
--- a/overlay/gem-interrupts.h
+++ b/overlay/gem-interrupts.h
@@ -30,6 +30,7 @@
struct gem_interrupts {
long unsigned last_count, count, delta;
int error;
+ int fd;
};
int gem_interrupts_init(struct gem_interrupts *irqs);