「カーネルの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のままなのです)
[
☆コメント]
[
△先頭へ]