[Intel-gfx] [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage

Ben Widawsky ben at bwidawsk.net
Tue Apr 5 21:33:35 CEST 2011


Added the mechnanism to communicate with the i915 IOCTL interface, and
removed the existing forcewake code, as it is not reliable.

Modified gpu_top to take a flag -i, to use the IOCTL interface. Previous
gpu_top behavior with no args is maintained from previous version.

Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 lib/intel_gpu_tools.h |   58 +++++++++++++++++++++++++++++++++++++++++++++++-
 lib/intel_mmio.c      |   18 +++++++++++++++
 tools/intel_gpu_top.c |   45 +++++++++++--------------------------
 3 files changed, 88 insertions(+), 33 deletions(-)

diff --git a/lib/intel_gpu_tools.h b/lib/intel_gpu_tools.h
index acee657..b45d6f9 100644
--- a/lib/intel_gpu_tools.h
+++ b/lib/intel_gpu_tools.h
@@ -26,29 +26,83 @@
  */
 
 #include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
 #include <sys/types.h>
+#include <sys/ioctl.h>
 #include <pciaccess.h>
 
 #include "intel_chipset.h"
 #include "intel_reg.h"
+#include "i915_drm.h"
 
 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
 
 extern void *mmio;
+extern int mmio_fd;
+extern int use_ioctl_mmio;
 void intel_get_mmio(struct pci_device *pci_dev);
 
+#define INREG(reg) \
+	(use_ioctl_mmio ? INREG_IOCTL(reg) : INREG_PCI(reg))
+
+#define OUTREG(reg, val) \
+	(use_ioctl_mmio ? OUTREG_IOCTL(reg, val) : OUTREG_PCI(reg, val))
+
 static inline uint32_t
-INREG(uint32_t reg)
+INREG_PCI(uint32_t reg)
 {
 	return *(volatile uint32_t *)((volatile char *)mmio + reg);
 }
 
+/*
+ * Try to read a register using the i915 IOCTL interface. The operations should
+ * not fall back to the normal pci mmio method to avoid confusion. IOCTL usage
+ * should be explicitly specified.
+ */
+static inline uint32_t
+INREG_IOCTL(uint32_t reg)
+{
+	int err;
+	struct drm_intel_read_reg reg_read = {
+		.offset = reg,
+		.size = 0
+	};
+
+	assert(mmio_fd >= 0);
+	err = ioctl(mmio_fd, DRM_IOCTL_I915_READ_REGISTER, &reg_read);
+	if (err)
+		fprintf(stderr, "read 0x%08x fail %s\n", reg, strerror(err));
+	return (uint32_t)reg_read.value;
+}
+
 static inline void
-OUTREG(uint32_t reg, uint32_t val)
+OUTREG_PCI(uint32_t reg, uint32_t val)
 {
 	*(volatile uint32_t *)((volatile char *)mmio + reg) = val;
 }
 
+/*
+ * See INREG_IOCTL()
+ */
+
+static inline void
+OUTREG_IOCTL(uint32_t reg, uint32_t val)
+{
+	int err;
+	struct drm_intel_write_reg reg_write = {
+		.offset = reg,
+		.size = 4,
+		.value = (uint64_t)val
+	};
+
+	assert(mmio_fd >= 0);
+	err = ioctl(mmio_fd, DRM_IOCTL_I915_WRITE_REGISTER, &reg_write);
+	if (err)
+		fprintf(stderr, "write 0x%08x fail %s\n", reg, strerror(err));
+}
+
 struct pci_device *intel_get_pci_device(void);
 
 uint32_t intel_get_drm_devid(int fd);
diff --git a/lib/intel_mmio.c b/lib/intel_mmio.c
index 0228a87..a98c9c7 100644
--- a/lib/intel_mmio.c
+++ b/lib/intel_mmio.c
@@ -40,6 +40,9 @@
 #include "intel_gpu_tools.h"
 
 void *mmio;
+int mmio_fd = -1;
+/* ioctls are not default */
+int use_ioctl_mmio = 0;
 
 void
 intel_map_file(char *file)
@@ -60,6 +63,9 @@ intel_map_file(char *file)
 			    strerror(errno));
 		    exit(1);
 	}
+
+	mmio_fd = fd;
+
 	close(fd);
 }
 
@@ -87,5 +93,17 @@ intel_get_mmio(struct pci_device *pci_dev)
 			strerror(err));
 		exit(1);
 	}
+
+	if (!use_ioctl_mmio)
+		return;
+
+	/* XXX: this is major lame, we need to have the device file match the
+	 * pci_dev, any good way to do that? */
+	mmio_fd = drm_open_any();
+	if (mmio_fd == -1) {
+		fprintf(stderr, "Couldn't get an fd for gen6 device\n");
+		exit(1);
+	}
+
 }
 
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index e9fbf43..b8ade4a 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <err.h>
+#include <string.h>
 #include <sys/ioctl.h>
 #include "intel_gpu_tools.h"
 #include "instdone.h"
@@ -297,33 +298,6 @@ struct ring {
 	int idle;
 };
 
-static void gen6_force_wake_get(void)
-{
-	int count;
-
-	if (!IS_GEN6(devid))
-		return;
-
-	/* This will probably have undesirable side-effects upon the system. */
-	count = 0;
-	while (count++ < 50 && (INREG(FORCEWAKE_ACK) & 1))
-		usleep(10);
-
-	OUTREG(FORCEWAKE, 1);
-
-	count = 0;
-	while (count++ < 50 && (INREG(FORCEWAKE_ACK) & 1) == 0)
-		usleep(10);
-}
-
-static void gen6_force_wake_put(void)
-{
-	if (!IS_GEN6(devid))
-		return;
-
-	OUTREG(FORCEWAKE, 0);
-}
-
 static uint32_t ring_read(struct ring *ring, uint32_t reg)
 {
 	return INREG(ring->mmio + reg);
@@ -331,9 +305,7 @@ static uint32_t ring_read(struct ring *ring, uint32_t reg)
 
 static void ring_init(struct ring *ring)
 {
-	gen6_force_wake_get();
 	ring->size = (((ring_read(ring, RING_LEN) & RING_NR_PAGES) >> 12) + 1) * 4096;
-	gen6_force_wake_put();
 }
 
 static void ring_reset(struct ring *ring)
@@ -348,10 +320,8 @@ static void ring_sample(struct ring *ring)
 	if (!ring->size)
 		return;
 
-	gen6_force_wake_get();
 	ring->head = ring_read(ring, RING_HEAD) & HEAD_ADDR;
 	ring->tail = ring_read(ring, RING_TAIL) & TAIL_ADDR;
-	gen6_force_wake_put();
 
 	if (ring->tail == ring->head)
 		ring->idle++;
@@ -397,11 +367,24 @@ int main(int argc, char **argv)
 	};
 	int i;
 
+	if (argc == 2) {
+		if ((strlen(argv[1]) == 2) &&
+		     !strncmp(argv[1], "-i", 2)) {
+			printf("using ioctl mmio access\n");
+			use_ioctl_mmio = 1;
+		     }
+	}
+
 	pci_dev = intel_get_pci_device();
 	devid = pci_dev->device_id;
 	intel_get_mmio(pci_dev);
 	init_instdone_definitions(devid);
 
+	if (IS_GEN6(devid) && !use_ioctl_mmio)
+		fprintf(stderr, "using ioctl for mmio "
+			" read/write is recommended (%s -i)\n",
+			argv[0]);
+
 	for (i = 0; i < num_instdone_bits; i++) {
 		top_bits[i].bit = &instdone_bits[i];
 		top_bits[i].count = 0;
-- 
1.7.3.4




More information about the Intel-gfx mailing list