パスワードを忘れた? アカウント作成
481209 journal

witchの日記: (ROBO)(作業メモ) HZを変更したらNICがLinkUpしなくなった原因 2

日記 by witch

「カーネルのHZを変更したらNICが動かなくなった」件、答えらしきものを見付けたのでメモ。

NICのドライバ /drivers/net/ep93xx_eth.c から eth_init()に "Link is down" の文字を見付け、phy_init(), phy_autoNegotiation()と順に辿っていくと

mdelay(1000);//delay 1 second.

という行が。
待ち時間 mdelay(1000)でレジスタからの値読み出しを3回繰り返してNGだと"Link is down"。
もしかしてこれ??

そして mdelay()の実体を求めて /include/linux/delay.h へ行くと

#define mdelay(n) (\
        {unsigned long __ms=(n); while (__ms--) udelay(1000);})

さらに udelay() の実体を求めて/include/asm-arm/delay.h へと辿ると、

#define udelay(n)                                               \
        (__builtin_constant_p(n) ?                              \
          ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :      \
                        __const_udelay((n) * 0x68dbul)) :       \
          __udelay(n))

ここで、実体を辿れなくなって「???」と思っていたら、実体はアセンブラ。
/arch/arm/lib/delay.S
ここのコメントに

* loops = (r0 * 0x10c6 * 100 * loops_per_jiffy) / 2^32

とあって、「100ってもしかしてHZの100?」という気がするけど、ARMのアセンブラを理解できない。

「mdelay()の宣言を udelay(10000) に変えちゃおうか…」
と思っていたのだけど、ふと気づいて「arm linux delay.S HZ」とかでぐぐってみると、新しいカーネルではパッチあたってる模様。
Linux-2.6.16 と2.6.17のdelay.Sのdiff
コメントには

* loops = r0 * HZ * loops_per_jiffy / 1000000

udelayの実体がHZを考慮しないコードになってたのね。(と思う…)

ここだけ変えて直るのかな…、他のソースも比較しなきゃだめかも。
(Armadilloの開発環境で配られてるのは、まだ2.6.12のままなのです)

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • カーネルのデバドラ見ながらHackですか
    懐かしいな。

    そんなもん、やってみて、動けば結果オーライなのでは。
    いつまでも悩む必要なんて無いっすよ。
    • by witch (3127) on 2007年10月31日 19時35分 (#1242655) 日記
      > そんなもん、やってみて、動けば結果オーライなのでは。

      カーネル(といってもNICのドライバだけど)のソースを追いかけたのって初めてで、ちょっと楽しかったのでメモしちゃいました。
      2.6.17のコードを持ってきたら動いた(ように見える)ので解決かなーと思っています。

      BAKさんからは「HZいじるよりもsched_hoge()使ったほうがいいんじゃないの?」と助言を受けてます。
      親コメント
typodupeerror

人生unstable -- あるハッカー

読み込み中...