#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include "gem-interrupts.h"
#include "debugfs.h"
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)
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;
}
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;