我有一個需要微秒延遲的驅動程序。爲了創建這個延遲,我的驅動程序正在使用內核的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