diff mbox

[intel-gpu-tools,1/3] intel-gpu-tools add ioctl interface usage

Message ID 1302032017-1771-2-git-send-email-ben@bwidawsk.net (mailing list archive)
State New, archived
Headers show

Commit Message

Ben Widawsky April 5, 2011, 7:33 p.m. UTC
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@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(-)

Comments

Kenneth Graunke April 6, 2011, 6:38 p.m. UTC | #1
On 04/05/2011 12:33 PM, Ben Widawsky wrote:
> 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@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(-)

One high level comment and a nitpick...

I'm a bit surprised that there's a command line option to use the IOCTL 
interface (i.e. non-broken mode).  Shouldn't it try the IOCTL and, if 
the kernel doesn't support it, fall back to using MMIO?

Or, perhaps better...try using the IOCTL by default on gen6, and if it 
fails, print a message like "Your kernel doesn't support the necessary 
IOCTLs; please upgrade or run intel_gpu_top -m to force MMIO mode (which 
may be inaccurate)." and quit.

> +#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);
>   }

As long as you're renaming these, can we please use lowercase for inline 
functions, while keeping the INREG/OUTREG macros uppercase?

> +/*
> + * 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.
> + */
diff mbox

Patch

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;