Reading timestamp register using I915_READ64 returns incorrect value containing only 32-bits of usable timestamp on x86_64. Let's use I915_READ64_2x32 to expose missing bits and swap dwords to stay compatible with old userspace. v2: Renamed macro used for swapping dwords to be more like swab.h macros. Added comments. Signed-off-by: Michał Winiarski <michal.winiarski@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_uncore.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0b0f4f8..c47372e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -40,6 +40,13 @@ #define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32(dev_priv__, reg__) +/* swap half-words in qword + * __swahw64(0x0123456789ABCDEF) is 0x89ABCDEF01234567 + */ +#define __swahw64(x) ((__u64)( \ + (((__u64)(x) & (__u64)0x00000000ffffffffULL) << 32) | \ + (((__u64)(x) & (__u64)0xffffffff00000000ULL) >> 32))) + static void assert_device_not_suspended(struct drm_i915_private *dev_priv) { @@ -989,7 +996,8 @@ int i915_reg_read_ioctl(struct drm_device *dev, switch (entry->size) { case 8: - reg->val = I915_READ64(reg->offset); + /* Use 2x32 read, otherwise it's possible to get corrupted results */ + reg->val = I915_READ64_2x32(reg->offset, reg->offset + 4); break; case 4: reg->val = I915_READ(reg->offset); @@ -1006,6 +1014,10 @@ int i915_reg_read_ioctl(struct drm_device *dev, goto out; } + /* To maintain compatibility with old userspace we need to swap dwords */ + if (reg->offset == RING_TIMESTAMP(RENDER_RING_BASE)) + reg->val = __swahw64(reg->val); + out: intel_runtime_pm_put(dev_priv); return ret; -- 1.9.3 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx