mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-29 12:50:50 +02:00
i965: Use updated kernel interface for accurate TIMESTAMP reads
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 c8d3ebaffc
Author: Chris Wilson <chris@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 hardware
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@chris-wilson.co.uk>
Cc: Martin Peres <martin.peres@linux.intel.com>
Cc: Kenneth Graunke <kenneth@whitecape.org>
Cc: Michał Winiarski <michal.winiarski@intel.com>
Cc: Daniel Vetter <daniel@ffwll.ch>
Tested-and-acked-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Daniel Vetter <daniel@ffwll.ch>
This commit is contained in:
parent
30f97b5e52
commit
013d731a67
3 changed files with 50 additions and 18 deletions
|
|
@ -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 left-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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, &dummy))
|
||||
return false;
|
||||
} while ((dummy & 0xffffffff) == 0 && --loop);
|
||||
if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP | 1, &dummy) == 0)
|
||||
return 3;
|
||||
|
||||
return loop > 0;
|
||||
/* 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 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;
|
||||
}
|
||||
|
||||
/* No advancement? No timestamp! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue