[Mesa-dev] [PATCH] i965: Use updated kernel interface for accurate TIMESTAMP reads
Chris Forbes
chrisf at ijw.co.nz
Wed Jul 22 23:35:11 PDT 2015
This fixes my HSW getting dropped back to 3.2 most of the time, and
seems like the reasonable thing to do.
Tested-and-acked-by: Chris Forbes <chrisf at ijw.co.nz>
On Tue, Jul 21, 2015 at 11:58 PM, Chris Wilson <chris at chris-wilson.co.uk> wrote:
> I was mistaken, I thought we already had fixed this in the kernel a
> couple of years ago. We had not, and the broken read (the hardware
> shifts the register output on 64bit kernels, but not on 32bit kernels) is
> now enshrined into the ABI. I also had the buggy architecture reversed,
> believing it to be 32bit that had the shifted results. On the basis of
> those mistakes, I wrote
>
> commit c8d3ebaffc0d7d915c1c19d54dba61fd1e57b338
> Author: Chris Wilson <chris at chris-wilson.co.uk>
> Date: Wed Apr 29 13:32:38 2015 +0100
>
> i965: Query whether we have kernel support for the TIMESTAMP register once
>
> Now that we do have an extended register read interface for always
> reporting the full 36bit TIMESTAMP (irrespective of whether the kernel
> is buggy or not), make use of it and in the process fix my reversed
> detection of the buggy reads for unpatched kernels.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Martin Peres <martin.peres at linux.intel.com>
> Cc: Kenneth Graunke <kenneth at whitecape.org>
> Cc: MichaĆ Winiarski <michal.winiarski at intel.com>
> Cc: Daniel Vetter <daniel at ffwll.ch>
> ---
> src/mesa/drivers/dri/i965/brw_queryobj.c | 15 ++++++++--
> src/mesa/drivers/dri/i965/intel_screen.c | 49 +++++++++++++++++++++++---------
> src/mesa/drivers/dri/i965/intel_screen.h | 2 +-
> 3 files changed, 49 insertions(+), 17 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
> index aea4d9b..6f1accd 100644
> --- a/src/mesa/drivers/dri/i965/brw_queryobj.c
> +++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
> @@ -497,13 +497,22 @@ brw_get_timestamp(struct gl_context *ctx)
> struct brw_context *brw = brw_context(ctx);
> uint64_t result = 0;
>
> - drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result);
> + switch (brw->intelScreen->hw_has_timestamp) {
> + case 3: /* New kernel, always full 36bit accuracy */
> + drm_intel_reg_read(brw->bufmgr, TIMESTAMP | 1, &result);
> + break;
> + case 2: /* 64bit kernel, result is right-shifted by 32bits, losing 4bits */
> + drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result);
> + result = result >> 32;
> + break;
> + case 1: /* 32bit kernel, result is 36bit wide but may be inaccurate! */
> + drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result);
> + break;
> + }
>
> /* See logic in brw_queryobj_get_results() */
> - result = result >> 32;
> result *= 80;
> result &= (1ull << 36) - 1;
> -
> return result;
> }
>
> diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
> index 1470b05..65a1766 100644
> --- a/src/mesa/drivers/dri/i965/intel_screen.c
> +++ b/src/mesa/drivers/dri/i965/intel_screen.c
> @@ -1123,25 +1123,48 @@ intel_detect_swizzling(struct intel_screen *screen)
> return true;
> }
>
> -static bool
> +static int
> intel_detect_timestamp(struct intel_screen *screen)
> {
> - uint64_t dummy = 0;
> - int loop = 10;
> + uint64_t dummy = 0, last = 0;
> + int upper, lower, loops;
>
> - /*
> - * On 32bit systems, some old kernels trigger a hw bug resulting in the
> - * TIMESTAMP register being shifted and the low 32bits always zero. Detect
> - * this by repeating the read a few times and check the register is
> - * incrementing every 80ns as expected and not stuck on zero (as would be
> - * the case with the buggy kernel/hw.).
> + /* On 64bit systems, some old kernels trigger a hw bug resulting in the
> + * TIMESTAMP register being shifted and the low 32bits always zero.
> + *
> + * More recent kernels offer an interface to read the full 36bits
> + * everywhere.
> */
> - do {
> + if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP | 1, &dummy) == 0)
> + return 3;
> +
> + /* Determine if we have a 32bit or 64bit kernel by inspecting the
> + * upper 32bits for a rapidly changing timestamp.
> + */
> + if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP, &last))
> + return 0;
> +
> + upper = lower = 0;
> + for (loops = 0; loops < 10; loops++) {
> + /* The TIMESTAMP should change every 80ns, so several round trips
> + * through the kernel should be enough to advance it.
> + */
> if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP, &dummy))
> - return false;
> - } while ((dummy & 0xffffffff) == 0 && --loop);
> + return 0;
> +
> + upper += (dummy >> 32) != (last >> 32);
> + if (upper > 1) /* beware 32bit counter overflow */
> + return 2; /* upper dword holds the low 32bits of the timestamp */
> +
> + lower += (dummy & 0xffffffff) != (last & 0xffffffff);
> + if (lower > 1)
> + return 1; /* timestamp is unshifted */
> +
> + last = dummy;
> + }
>
> - return loop > 0;
> + /* No advancement? No timestamp! */
> + return 0;
> }
>
> /**
> diff --git a/src/mesa/drivers/dri/i965/intel_screen.h b/src/mesa/drivers/dri/i965/intel_screen.h
> index a741c94..fd5143e 100644
> --- a/src/mesa/drivers/dri/i965/intel_screen.h
> +++ b/src/mesa/drivers/dri/i965/intel_screen.h
> @@ -52,7 +52,7 @@ struct intel_screen
>
> bool hw_has_swizzling;
>
> - bool hw_has_timestamp;
> + int hw_has_timestamp;
>
> /**
> * Does the kernel support resource streamer?
> --
> 2.1.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list