2011-12-02 102 views
6

私はマイクロ秒の遅延を必要とするドライバを持っています。この遅延を作成するために、私のドライバはカーネルの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上に存在します。

答えて

2

E5700はX86_FEATURE_CONSTANT_TSCですが、X86_FEATURE_NONSTOP_TSCはありません。 TSCは、udelayの可能性のあるクロックソースです。アフィニティマスクを持つコアのいずれかにバインドされていない場合、udelayの間、タスクは別のCPUに先取りされ、再スケジューリングされている可能性があります。または、TSCが低電力CPUモードで安定していない可能性があります。

udelay中に割り込みを無効にするか、プリエンプションを無効にすることはできますか?また、前と後のTSCを読んでみてください。

+0

私はそれを試してあなたにお返しします。各コアには独自のTSCがあるので、ドライバが処理しているプロセスが別のCPUに再スケジューリングされた場合、TSCは同じではないかもしれません。 また、X86_FEATURE_CONSTANT_TSCは周波数スケーリングに関係なくCPUのTSCが安定していることを意味し、X86_FEATURE_NONSTOP_TSCはTSCがカウントを停止しないことを意味します。もしそうなら、いつCPUがTSCを停止しますか? –

+0

特定の[C-States](http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states)中にTSCが停止することがあります。 –

+2

[TSCベースの遅延コード](http://lxr.linux.no/#linux+v2.6.38/arch/x86/lib/delay.c#L51)は、遅延中にCPU間で移動することを適切に考慮しています。遅延中にTSCが停止すると、遅れ*が長くなるだけで、短くはない*ので、問題はありません。 – caf

3

私はそのバージョンのカーネルのバグについては知らない(しかし、そうではないという意味ではない)。

udelay()は、「中断できません」 - プリエンプションを無効にしないため、遅延中にタスクをRTタスクが先取りすることができます。ただし、代替遅延の実装についても同じことが言えるので、問題になる可能性は低いです。

あなたの実際の問題はDMAコヒーレンシ/メモリオーダーの問題でしょうか?代わりの遅延実装がバスにアクセスするため、実際の問題が副作用として隠れている可能性があります。

+0

申し訳ありませんが、私は "uninterruptible"の意味は、呼び出しが遅れていれば一度だけ戻ってくるということでした。 このドライバでは、私はDMAを使用していません。 キャッシュコヒーレンシの問題に関しては、デバイスはPCI-Express FPGAです。デバイスを調査するとき、I/O領域を要求し、すべてのI/O機能で使用されるベースアドレスを取得するためにioremap_nocache()を使用します。私はioremap_nocache()を使用してキャッシュの一貫性を保証すると思った? –

関連する問題