私はマイクロ秒の遅延を必要とするドライバを持っています。この遅延を作成するために、私のドライバはカーネルの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 Pentium Dual Core(E5700)でカーネル2.6.38-11-generic SMP(Kubuntu 11.04、x86_64)を実行しています。
私が知る限り、文書には、の実行が指定された遅延の少なくともで遅れ、中断されないことが記載されています。 このバージョンのカーネルにバグがありますか、または私はudelayの使用について何か誤解しましたか?
問題があまりにも早く戻っudelayによって引き起こされたことを自分自身を納得させるために、我々は、I/Oポートのいずれかに100kHzのクロックを供給し、次のように私たち自身の遅延を実装:
// 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を停止しますか? –
特定の[C-States](http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states)中にTSCが停止することがあります。 –
[TSCベースの遅延コード](http://lxr.linux.no/#linux+v2.6.38/arch/x86/lib/delay.c#L51)は、遅延中にCPU間で移動することを適切に考慮しています。遅延中にTSCが停止すると、遅れ*が長くなるだけで、短くはない*ので、問題はありません。 – caf