2007年06月26日Tue [10:11] Linux  

Kernel-2.6.21でのrequest_irq&free_irq

納品の時期ですっかりBlogのことを忘れてた。
というわけで久しぶりに更新。

Kernel2.6.20を今まで使っていて、今回2.6.21に変更したら
担当ドライバをinsmodしたときにNULLポインタにアクセスして
カーネルパニックを起こすようになっちゃった。
そんなわけで、コードの見直しを迫られたわけですが、
どうやら、request_irq近辺で落ちているらしい。
で、コンソールにデバッグ出力させたら、どうやらrequest_irqで
登録するhandlerがなぜか呼ばれていると。
このドライバでは、ユーザがinit処理を呼び出してから割り込みが
発生するという前提の下、作られていたわけで
insmod時に割り込みハンドラが呼ばれたせいでinit処理していない変数を
参照したためにNULLポインタアクセスエラーになったという落ちでした。

で、request_irqの何が変わったんだということを調べると
#ifdef CONFIG_DEBUG_SHIRQ
 if (irqflags & IRQF_SHARED) {
 /*
 * It's a shared IRQ -- the driver ought to be prepared for it
 * to happen immediately, so let's make sure....
 * We do this before actually registering it, to make sure that
 * a 'real' IRQ doesn't run in parallel with our fake
 */
 if (irqflags & IRQF_DISABLED) {
  unsigned long flags;
  local_irq_save(flags);
  handler(irq, dev_id);
  local_irq_restore(flags);
 } else
  handler(irq, dev_id);
 }
#endif


kernel/irq/manage.cでrequest_irq()やらfree_irq()が定義されているわけだけど
Kernel-2.6.21と2.6.20を見比べると、上のコードが追加されている。
んー、要するにSA_SHIRQ(上のコードだとIRQF_SHAREDだけど同値だから同じこと)を
request_irqのflagで指定していて、Kernelの.configでCONFIG_DEBUG_SHIRQを
有効にしていた場合、request_irq()を呼び出したら、内部で登録しようとしている
handlerを必ず呼び出すということらしい。
英語のコメントを適当に訳すと

ドライバは割り込みハンドラを起こさせる用意ができていなければならない。
だからカーネルは本物の割り込みが発生する前の登録する前にそのハンドラを実行しますよ。


とかいうことらしい。(合ってるか知らんけど)
そんなわけで、request_irq()で登録するhandlerは登録するときに
呼ばれるようになったということで、気をつけましょう。
ついでに、free_irq()でも同じようにhandlerを呼び出すようにしているんで
こちらも注意。

Re Comments.

Comment Form.

  管理者にだけ表示を許可する