我有一个需要微秒延迟的驱动程序。为了创建这个延迟,我的驱动程序正在使用内核的udelay函数。具体而言,有一个呼叫udelay的(90):Linux内核:udelay()返回得太早?
iowrite32(data, addr + DATA_OFFSET);
iowrite32(trig, addr + CONTROL_OFFSET);
udelay(30);
trig |= 1;
iowrite32(trig, addr + CONTROL_OFFSET);
udelay(90); // This is the problematic call
我们有可靠性问题与设备。经过很多调试,我们将问题追溯到驱动程序在90us过去之前恢复。 (请参阅下面的“证明”。)
我在Intel奔腾双核(E5700)上运行内核版本2.6.38-11-通用SMP(Kubuntu 11.04,x86_64)。
据我所知,文档指出udelay的将推迟至少指定的延迟执行,并且是不间断。 这个版本的内核有bug吗,还是误解了udelay的使用?
要说服自己,认为该问题是由udelay的返回太早造成的,我们给100kHz的时钟的I/O端口之一,并实现了自己的延迟如下:
// Wait until n number of falling edges
// are observed
void clk100_delay(void *addr, u32 n) {
int i;
for (i = 0; i < n; i++) {
u32 prev_clk = ioread32(addr);
while (1) {
u32 clk = ioread32(addr);
if (prev_clk && !clk) {
break;
} else {
prev_clk = clk;
}
}
}
}
...和司机现在完美地工作。
最后一点,我发现a discussion表明频率缩放可能会造成功能无法正常运作的*延迟()系列,但这是一个ARM邮件列表上 - 我假设这样的问题将是不可存在于基于Linux x86的PC上。
我会尝试一下并回复你。我的理解是正确的,每个核心都有自己的TSC,所以如果我的驱动程序正在维修的过程被重新调度到另一个CPU,那么TSC可能会不一样? 另外,我是否正确理解X86_FEATURE_CONSTANT_TSC表示CPU的TSC稳定,无论频率调整如何,X86_FEATURE_NONSTOP_TSC意味着TSC将永不停止计数?如果是这样,CPU何时会暂停TSC? –
TSC可能会在特定[C-States]期间停机(http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states)。 –
在延迟期间[基于TSC的延迟代码](http://lxr.linux.no/#linux+v2.6.38/arch/x86/lib/delay.c#L51)正确说明在CPU之间发生了移位。 TSC在延迟期间停止会使延迟更长*,而不是更短*,所以这也不是问题。 – caf