intel-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* read/write ioctl usage in intel-gpu-tools, for review
@ 2011-04-05 19:33 Ben Widawsky
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage Ben Widawsky
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Ben Widawsky @ 2011-04-05 19:33 UTC (permalink / raw)
  To: intel-gfx


Here is the beginning of the port of intel-gpu-tools. It buys us enough
to not be completely broken with the 3 apps I find most important. We
badly need some kind of global arg parsing for our tools, as well as
port the rest of the tools to use INREG/OUTREG, instead of relying on
mmio, but I will save that for another day.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage
  2011-04-05 19:33 read/write ioctl usage in intel-gpu-tools, for review Ben Widawsky
@ 2011-04-05 19:33 ` Ben Widawsky
  2011-04-06 18:38   ` Kenneth Graunke
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 2/3] intel-gpu-tools update reg_read to use ioctls Ben Widawsky
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 3/3] intel-gpu-tools: update reg_write to use ioctl interface Ben Widawsky
  2 siblings, 1 reply; 5+ messages in thread
From: Ben Widawsky @ 2011-04-05 19:33 UTC (permalink / raw)
  To: intel-gfx

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(-)

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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [intel-gpu-tools] [PATCH 2/3] intel-gpu-tools update reg_read to use ioctls
  2011-04-05 19:33 read/write ioctl usage in intel-gpu-tools, for review Ben Widawsky
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage Ben Widawsky
@ 2011-04-05 19:33 ` Ben Widawsky
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 3/3] intel-gpu-tools: update reg_write to use ioctl interface Ben Widawsky
  2 siblings, 0 replies; 5+ messages in thread
From: Ben Widawsky @ 2011-04-05 19:33 UTC (permalink / raw)
  To: intel-gfx

Redid the arg parsing as well as the register dumps to easily support
switching between ioctl, and non-ioctl usage.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 tools/intel_reg_read.c |   41 +++++++++++++++++++++++++++++------------
 1 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/tools/intel_reg_read.c b/tools/intel_reg_read.c
index 0259924..d7c4962 100644
--- a/tools/intel_reg_read.c
+++ b/tools/intel_reg_read.c
@@ -22,7 +22,7 @@
  *
  * Authors:
  *	Zhenyu Wang <zhenyuw@linux.intel.com>
- *
+ *	Ben Widawsky <ben@bwidawsk.net>
  */
 
 #include <unistd.h>
@@ -30,32 +30,49 @@
 #include <stdio.h>
 #include <err.h>
 #include <string.h>
+#include <unistd.h>
 #include "intel_gpu_tools.h"
 
 static void dump_range(uint32_t start, uint32_t end)
 {
 	int i;
-
 	for (i = start; i < end; i += 4)
-		printf("0x%X : 0x%X\n", i,
-		       *(volatile uint32_t *)((volatile char*)mmio + i));
+		printf("0x%X : 0x%X\n", i, INREG(i));
+}
+
+static void usage(const char *app_name)
+{
+	printf("Usage: %s -i [-f | addr]\n", app_name);
+	printf("\t -i : use IOCTL read/write driver interface.\n");
+	printf("\t -f : read back full range of registers.\n");
+	printf("\t      WARNING! This could be danger to hang the machine!\n");
+	exit(1);
 }
 
 int main(int argc, char** argv)
 {
 	uint32_t reg;
+	int opt;
+	int do_range_dump = 0;
 
-	if (argc != 2) {
-		printf("Usage: %s [-f | addr]\n", argv[0]);
-		printf("\t -f : read back full range of registers.\n");
-		printf("\t      WARNING! This could be danger to hang the machine!\n");
-		printf("\t addr : in 0xXXXX format\n");
-		exit(1);
+	while ((opt = getopt(argc, argv, "ifh?")) != -1) {
+		switch (opt) {
+		case 'i':
+			use_ioctl_mmio = 1;
+			break;
+		case 'f':
+			do_range_dump = 1;
+			break;
+		case 'h':
+		case '?':
+			usage(argv[0]);
+			exit(EXIT_FAILURE);
+		}
 	}
 
 	intel_get_mmio(intel_get_pci_device());
 
-	if (!strcmp(argv[1], "-f")) {
+	if (do_range_dump) {
 		dump_range(0x00000, 0x00fff);   /* VGA registers */
 		dump_range(0x02000, 0x02fff);   /* instruction, memory, interrupt control registers */
 		dump_range(0x03000, 0x031ff);   /* FENCE and PPGTT control registers */
@@ -71,7 +88,7 @@ int main(int argc, char** argv)
 		dump_range(0x70000, 0x72fff);   /* display and cursor registers */
 		dump_range(0x73000, 0x73fff);   /* performance counters */
 	} else {
-		sscanf(argv[1], "0x%x", &reg);
+		reg = strtol(argv[optind], NULL, 0);
 		dump_range(reg, reg + 4);
 	}
 
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [intel-gpu-tools] [PATCH 3/3] intel-gpu-tools: update reg_write to use ioctl interface
  2011-04-05 19:33 read/write ioctl usage in intel-gpu-tools, for review Ben Widawsky
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage Ben Widawsky
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 2/3] intel-gpu-tools update reg_read to use ioctls Ben Widawsky
@ 2011-04-05 19:33 ` Ben Widawsky
  2 siblings, 0 replies; 5+ messages in thread
From: Ben Widawsky @ 2011-04-05 19:33 UTC (permalink / raw)
  To: intel-gfx

we really need a global arg parser... :(

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 tools/intel_reg_write.c |   44 ++++++++++++++++++++++++++++++++------------
 1 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/tools/intel_reg_write.c b/tools/intel_reg_write.c
index c8af9bb..158f5f8 100644
--- a/tools/intel_reg_write.c
+++ b/tools/intel_reg_write.c
@@ -22,6 +22,7 @@
  *
  * Authors:
  *    Ben Gamari <bgamari.foss@gmail.com>
+ *    Ben Widawsky <ben@bwidawsk.net>
  *
  */
 
@@ -31,26 +32,45 @@
 #include <err.h>
 #include "intel_gpu_tools.h"
 
+static void usage(const char *app_name)
+{
+	printf("Usage: %s [-i] addr value\n", app_name);
+	printf("  -i: use IOCTL read/write driver interface.\n");
+	printf("  WARNING: This is dangerous to you and your system's health.\n");
+	printf("           Only for use in debugging.\n");
+	exit(1);
+}
+
 int main(int argc, char** argv)
 {
 	uint32_t reg, value;
-	volatile uint32_t *ptr;
+	int opt;
 
-	if (argc < 3) {
-		printf("Usage: %s addr value\n", argv[0]);
-		printf("  WARNING: This is dangerous to you and your system's health.\n");
-		printf("           Only for use in debugging.\n");
-		exit(1);
+	while ((opt = getopt(argc, argv, "ih?")) != -1) {
+		switch (opt) {
+		case 'i':
+			use_ioctl_mmio = 1;
+			break;
+		case 'h':
+		case '?':
+			usage(argv[0]);
+			exit(EXIT_FAILURE);
+		}
 	}
+	if (argc - optind != 2) {
+		usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+
+	reg = strtol(argv[optind], NULL, 0);
+	value = strtol(argv[optind + 1], NULL, 0);
 
 	intel_get_mmio(intel_get_pci_device());
-	sscanf(argv[1], "0x%x", &reg);
-	sscanf(argv[2], "0x%x", &value);
-	ptr = (volatile uint32_t *)((volatile char *)mmio + reg);
 
-	printf("Value before: 0x%X\n", *ptr);
-	*ptr = value;
-	printf("Value after: 0x%X\n", *ptr);
+	printf("Value before: 0x%X\n", INREG(reg));
+	OUTREG(reg, value);
+	printf("Value after: 0x%X\n", INREG(reg));
 
 	return 0;
 }
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage
  2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage Ben Widawsky
@ 2011-04-06 18:38   ` Kenneth Graunke
  0 siblings, 0 replies; 5+ messages in thread
From: Kenneth Graunke @ 2011-04-06 18:38 UTC (permalink / raw)
  To: intel-gfx

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-04-06 18:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-05 19:33 read/write ioctl usage in intel-gpu-tools, for review Ben Widawsky
2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 1/3] intel-gpu-tools add ioctl interface usage Ben Widawsky
2011-04-06 18:38   ` Kenneth Graunke
2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 2/3] intel-gpu-tools update reg_read to use ioctls Ben Widawsky
2011-04-05 19:33 ` [intel-gpu-tools] [PATCH 3/3] intel-gpu-tools: update reg_write to use ioctl interface Ben Widawsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).