mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 06:33:31 +00:00
pc: avoid use usleep_range in m/udelay emulation
m/udelay is called with closed interrupts. Linux contrib code expects no other task to be run respectively to be re-scheduled. usleep_range leads to executing other tasks, which causes assertions in "spinlock taken twice" or "unexpected preempt count" errors, seen on runtime with wifi_drv and intel_fb. The assertion triggered with the changes by #4562.
This commit is contained in:
parent
6c5d2253c9
commit
e2b61231ae
@ -19,9 +19,6 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
extern u64 jiffies_64;
|
||||
|
||||
|
||||
static __always_inline void rep_nop(void)
|
||||
@ -33,8 +30,7 @@ static __always_inline void rep_nop(void)
|
||||
static __always_inline void cpu_relax(void)
|
||||
{
|
||||
/* break busy loop of slchi() in drivers/i2c/algos/i2c-algo-bit.c */
|
||||
u64 const us = jiffies_to_usecs(1);
|
||||
usleep_range(us, us);
|
||||
__udelay(100);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Supplement for emulation for linux/include/asm-generic/delay.h
|
||||
* \author Josef Soentgen
|
||||
* \author Alexander Boettcher
|
||||
* \date 2022-05-05
|
||||
*/
|
||||
|
||||
@ -14,21 +15,54 @@
|
||||
|
||||
#include <asm-generic/delay.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <lx_emul.h>
|
||||
|
||||
|
||||
void __const_udelay(unsigned long xloops)
|
||||
{
|
||||
unsigned long usecs = xloops / 0x10C7UL;
|
||||
if (usecs < 100)
|
||||
lx_emul_time_udelay(usecs);
|
||||
else
|
||||
usleep_range(usecs, usecs * 10);
|
||||
unsigned long const usecs = xloops / 0x10C7UL;
|
||||
__udelay(usecs);
|
||||
}
|
||||
|
||||
|
||||
void __udelay(unsigned long usecs)
|
||||
{
|
||||
lx_emul_time_udelay(usecs);
|
||||
/*
|
||||
* Account for delays summing up to equivalent of 1 jiffie during
|
||||
* jiffies_64 stays same. When 1 jiffie is reached in sum,
|
||||
* increase jiffie_64 to break endless loops, seen in
|
||||
* * intel_fb - cpu_relax(void) emulation used by
|
||||
* busy loop of slchi() in drivers/i2c/algos/i2c-algo-bit.c
|
||||
* * wifi_drv - net/wireless/intel/iwlwif* code during error code handling
|
||||
*/
|
||||
static uint64_t last_jiffie = 0;
|
||||
static unsigned long delayed_sum = 0;
|
||||
|
||||
if (jiffies_64 == last_jiffie) {
|
||||
delayed_sum += usecs;
|
||||
} else {
|
||||
last_jiffie = jiffies_64;
|
||||
delayed_sum = usecs;
|
||||
}
|
||||
|
||||
if (usecs < 100)
|
||||
lx_emul_time_udelay(usecs);
|
||||
else {
|
||||
unsigned long slept = 0;
|
||||
while (slept < usecs) {
|
||||
lx_emul_time_udelay(100);
|
||||
slept += 100;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When delays sum up to the equivalent of 1 jiffie,
|
||||
* increase it to break endless loops.
|
||||
*/
|
||||
if (delayed_sum >= jiffies_to_usecs(1)) {
|
||||
jiffies_64 ++;
|
||||
delayed_sum = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user