diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-04-30 18:39:27 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-04-30 18:44:48 +0100 |
commit | c864279de620a6e211b8a197dbdf9e3e1e2b60ab (patch) | |
tree | 818105bcc01e0713cded97034fded0e4bd9c0356 | |
parent | bff7ecde7bf3757e11ab4559212564e3f4919b89 (diff) |
overlay: Parse /proc/interrupts in lieu of debugfs/i915_gem_interrupt
So the interrupt counter was removed from i915_gem_interrupt, and if we
do not have the perf API available, we therefore need to read it from
/proc/interrupts instead.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | overlay/gem-interrupts.c | 101 |
1 files changed, 73 insertions, 28 deletions
diff --git a/overlay/gem-interrupts.c b/overlay/gem-interrupts.c index 15dc7919..48a36b85 100644 --- a/overlay/gem-interrupts.c +++ b/overlay/gem-interrupts.c @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <ctype.h> #include "gem-interrupts.h" #include "debugfs.h" @@ -48,16 +49,77 @@ static int perf_open(void) return perf_event_open(&attr, -1, 0, -1, 0); } -static int debugfs_open(void) +static long long debugfs_read(void) { - char buf[1024]; - struct stat st; + char buf[8192], *b; + int fd, len; sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path); - if (stat(buf, &st)) - return errno; + fd = open(buf, 0); + if (fd < 0) + return -1; - return 0; + len = read(fd, buf, sizeof(buf)-1); + close(fd); + + if (len < 0) + return -1; + + buf[len] = '\0'; + + b = strstr(buf, "Interrupts received:"); + if (b == NULL) + return -1; + + return strtoull(b + sizeof("Interrupts received:"), 0, 0); +} + +static long long procfs_read(void) +{ + char buf[8192], *b; + int fd, len; + unsigned long long val; + +/* 44: 51 42446 0 0 PCI-MSI-edge i915*/ + fd = open("/proc/interrupts", 0); + if (fd < 0) + return -1; + + len = read(fd, buf, sizeof(buf)-1); + close(fd); + + if (len < 0) + return -1; + + buf[len] = '\0'; + + b = strstr(buf, "i915"); + if (b == NULL) + return -1; + while (*--b != ':') + ; + + val = 0; + do { + while (isspace(*++b)) + ; + if (!isdigit(*b)) + break; + + val += strtoull(b, &b, 0); + } while(1); + + return val; +} + +static long long interrupts_read(void) +{ + long long val; + + val = debugfs_read(); + if (val < 0) + val = procfs_read(); + return val; } int gem_interrupts_init(struct gem_interrupts *irqs) @@ -65,8 +127,8 @@ 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(); + if (irqs->fd < 0 && interrupts_read() < 0) + irqs->error = ENODEV; return irqs->error; } @@ -80,26 +142,9 @@ int gem_interrupts_update(struct gem_interrupts *irqs) return irqs->error; 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; - - buf[len] = '\0'; - - b = strstr(buf, "Interrupts received:"); - if (b == NULL) - return irqs->error = ENOENT; - - val = strtoull(b + sizeof("Interrupts received:"), 0, 0); + val = interrupts_read(); + if (val < 0) + return irqs->error = ENODEV; } else { if (read(irqs->fd, &val, sizeof(val)) < 0) return irqs->error = errno; |