drivers/cavs_timer: Fix multiword race with timer counter
The count register is 64 bits, but we're a 32 bit CPU that can only read four bytes at a time, so a bit of care is needed to prevent racing against a wraparound of the low word. Wrap the low read between two reads of the high word and make sure it didn't change. Fixes #31599 Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
parent
bd1d0b22b5
commit
71fd58ccac
1 changed files with 16 additions and 1 deletions
|
@ -55,7 +55,22 @@ static void set_compare(uint64_t time)
|
||||||
|
|
||||||
static uint64_t count(void)
|
static uint64_t count(void)
|
||||||
{
|
{
|
||||||
return shim_regs->walclk;
|
/* The count register is 64 bits, but we're a 32 bit CPU that
|
||||||
|
* can only read four bytes at a time, so a bit of care is
|
||||||
|
* needed to prevent racing against a wraparound of the low
|
||||||
|
* word. Wrap the low read between two reads of the high word
|
||||||
|
* and make sure it didn't change.
|
||||||
|
*/
|
||||||
|
volatile uint32_t *wc = (void *)&shim_regs->walclk;
|
||||||
|
uint32_t hi0, hi1, lo;
|
||||||
|
|
||||||
|
do {
|
||||||
|
hi0 = wc[1];
|
||||||
|
lo = wc[0];
|
||||||
|
hi1 = wc[1];
|
||||||
|
} while (hi0 != hi1);
|
||||||
|
|
||||||
|
return (((uint64_t)hi0) << 32) | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t count32(void)
|
static uint32_t count32(void)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue