diff mbox

[v2] drm/i915: add register read IOCTL

Message ID 1342116066-12164-1-git-send-email-ben@bwidawsk.net (mailing list archive)
State Accepted
Headers show

Commit Message

Ben Widawsky July 12, 2012, 6:01 p.m. UTC
The interface's immediate purpose is to do synchronous timestamp queries
as required by GL_TIMESTAMP. The GPU has a register for reading the
timestamp but because that would normally require root access through
libpciaccess, the IOCTL can provide this service instead.

Currently the implementation whitelists only the render ring timestamp
register, because that is the only thing we need to expose at this time.

v2: make size implicit based on the register offset
Add a generation check

Cc: Eric Anholt <eric@anholt.net>
Cc: Jacek Lawrynowicz <jacek.lawrynowicz@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_dma.c |  1 +
 drivers/gpu/drm/i915/i915_drv.c | 46 +++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h |  2 ++
 drivers/gpu/drm/i915/i915_reg.h |  1 +
 include/drm/i915_drm.h          |  6 ++++++
 5 files changed, 56 insertions(+)

Comments

Eric Anholt July 18, 2012, 5:14 p.m. UTC | #1
Ben Widawsky <ben@bwidawsk.net> writes:

> The interface's immediate purpose is to do synchronous timestamp queries
> as required by GL_TIMESTAMP. The GPU has a register for reading the
> timestamp but because that would normally require root access through
> libpciaccess, the IOCTL can provide this service instead.
>
> Currently the implementation whitelists only the render ring timestamp
> register, because that is the only thing we need to expose at this time.
>
> v2: make size implicit based on the register offset
> Add a generation check

> diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
> index 8cc7083..fbe7757 100644
> --- a/include/drm/i915_drm.h
> +++ b/include/drm/i915_drm.h
> @@ -203,6 +203,7 @@ typedef struct _drm_i915_sarea {
>  #define DRM_I915_GEM_WAIT	0x2c
>  #define DRM_I915_GEM_CONTEXT_CREATE	0x2d
>  #define DRM_I915_GEM_CONTEXT_DESTROY	0x2e
> +#define DRM_I915_REG_READ	0x30

Is 0x2f some other outstanding ioctl?

Other than that,

Reviewed-by: Eric Anholt <eric@anholt.net>

Note: we have requests both by Arjan and by Valve for the functionality
that this patch will allow.
Ben Widawsky July 18, 2012, 5:22 p.m. UTC | #2
On Wed, 18 Jul 2012 10:14:46 -0700
Eric Anholt <eric@anholt.net> wrote:

> Ben Widawsky <ben@bwidawsk.net> writes:
> 
> > The interface's immediate purpose is to do synchronous timestamp queries
> > as required by GL_TIMESTAMP. The GPU has a register for reading the
> > timestamp but because that would normally require root access through
> > libpciaccess, the IOCTL can provide this service instead.
> >
> > Currently the implementation whitelists only the render ring timestamp
> > register, because that is the only thing we need to expose at this time.
> >
> > v2: make size implicit based on the register offset
> > Add a generation check
> 
> > diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
> > index 8cc7083..fbe7757 100644
> > --- a/include/drm/i915_drm.h
> > +++ b/include/drm/i915_drm.h
> > @@ -203,6 +203,7 @@ typedef struct _drm_i915_sarea {
> >  #define DRM_I915_GEM_WAIT	0x2c
> >  #define DRM_I915_GEM_CONTEXT_CREATE	0x2d
> >  #define DRM_I915_GEM_CONTEXT_DESTROY	0x2e
> > +#define DRM_I915_REG_READ	0x30
> 
> Is 0x2f some other outstanding ioctl?
>

I was saving it for some yet to be realized context ioctl. We can use
0x2f, I don't care. Daniel - feel free to change it or not as you
please when/if you suck it in.

> Other than that,
> 
> Reviewed-by: Eric Anholt <eric@anholt.net>
> 
> Note: we have requests both by Arjan and by Valve for the functionality
> that this patch will allow.
Daniel Vetter July 18, 2012, 6:12 p.m. UTC | #3
On Wed, Jul 18, 2012 at 10:22:01AM -0700, Ben Widawsky wrote:
> On Wed, 18 Jul 2012 10:14:46 -0700
> Eric Anholt <eric@anholt.net> wrote:
> 
> > Ben Widawsky <ben@bwidawsk.net> writes:
> > 
> > > The interface's immediate purpose is to do synchronous timestamp queries
> > > as required by GL_TIMESTAMP. The GPU has a register for reading the
> > > timestamp but because that would normally require root access through
> > > libpciaccess, the IOCTL can provide this service instead.
> > >
> > > Currently the implementation whitelists only the render ring timestamp
> > > register, because that is the only thing we need to expose at this time.
> > >
> > > v2: make size implicit based on the register offset
> > > Add a generation check
> > 
> > > diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
> > > index 8cc7083..fbe7757 100644
> > > --- a/include/drm/i915_drm.h
> > > +++ b/include/drm/i915_drm.h
> > > @@ -203,6 +203,7 @@ typedef struct _drm_i915_sarea {
> > >  #define DRM_I915_GEM_WAIT	0x2c
> > >  #define DRM_I915_GEM_CONTEXT_CREATE	0x2d
> > >  #define DRM_I915_GEM_CONTEXT_DESTROY	0x2e
> > > +#define DRM_I915_REG_READ	0x30
> > 
> > Is 0x2f some other outstanding ioctl?
> >
> 
> I was saving it for some yet to be realized context ioctl. We can use
> 0x2f, I don't care. Daniel - feel free to change it or not as you
> please when/if you suck it in.

Patch queued for -next (with ioctl number 0x31, I've figure when I'll
change it I might as well avoid conflicts with the set_cacheing stuff).
Can you please adjust the i-g-t test and commit that one, too?

Thanks, Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f64ef4b..5e20f11 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1851,6 +1851,7 @@  struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e754cdf..77deaea 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1152,3 +1152,49 @@  __i915_write(16, w)
 __i915_write(32, l)
 __i915_write(64, q)
 #undef __i915_write
+
+static const struct register_whitelist {
+	uint64_t offset;
+	uint32_t size;
+	uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
+} whitelist[] = {
+	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
+};
+
+int i915_reg_read_ioctl(struct drm_device *dev,
+			void *data, struct drm_file *file)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_reg_read *reg = data;
+	struct register_whitelist const *entry = whitelist;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
+		if (entry->offset == reg->offset &&
+		    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
+			break;
+	}
+
+	if (i == ARRAY_SIZE(whitelist))
+		return -EINVAL;
+
+	switch (entry->size) {
+	case 8:
+		reg->val = I915_READ64(reg->offset);
+		break;
+	case 4:
+		reg->val = I915_READ(reg->offset);
+		break;
+	case 2:
+		reg->val = I915_READ16(reg->offset);
+		break;
+	case 1:
+		reg->val = I915_READ8(reg->offset);
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 627fe35..2c0d840 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1529,6 +1529,8 @@  extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
 extern int intel_enable_rc6(const struct drm_device *dev);
 
 extern bool i915_semaphore_is_enabled(struct drm_device *dev);
+int i915_reg_read_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file);
 
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cc82871..33e66cc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -449,6 +449,7 @@ 
 #define RING_ACTHD(base)	((base)+0x74)
 #define RING_NOPID(base)	((base)+0x94)
 #define RING_IMR(base)		((base)+0xa8)
+#define RING_TIMESTAMP(base)	((base)+0x358)
 #define   TAIL_ADDR		0x001FFFF8
 #define   HEAD_WRAP_COUNT	0xFFE00000
 #define   HEAD_WRAP_ONE		0x00200000
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 8cc7083..fbe7757 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -203,6 +203,7 @@  typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_WAIT	0x2c
 #define DRM_I915_GEM_CONTEXT_CREATE	0x2d
 #define DRM_I915_GEM_CONTEXT_DESTROY	0x2e
+#define DRM_I915_REG_READ	0x30
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -249,6 +250,7 @@  typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_WAIT		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
 #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
 #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
+#define DRM_IOCTL_I915_REG_READ			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -918,4 +920,8 @@  struct drm_i915_gem_context_destroy {
 	__u32 pad;
 };
 
+struct drm_i915_reg_read {
+	__u64 offset;
+	__u64 val; /* Return value */
+};
 #endif				/* _I915_DRM_H_ */