2010年07月20日
Linux2.6.33を載せたKZM-CA9-01ボードでSDメモリカードがマウントできない(その1)
前回の経験により、2.6.33のカーネルをKZM-CA9-01ボード(Cortex-A9 Quad core)で動かすことはすぐにできました。
しかしSDメモリカードがマウントできません。
この問題についていろいろ調べた様子を2回にわたって紹介します。
Linux 2.6.33
前回話題に出たlinux-arm.orgのgitリポジトリにある2.6.33のソースにKZM-CA9-01ボード固有のパッチをあてて動かしてみました。2.6.33で追加されたPMU(パフォーマンスモニタ)はまだ実装していませんが、起動するところまではすぐにできました。
2.6.32で問題だったUSBメモリをルートファイルシステムとしてSMPでの起動もうまく動いています。
ただし2.6.32では問題がなかったSDメモリカードのマウントができなくなってしまいました。
androidのソースリポジトリにある2.6.35-rc3も動かしてみたのですが同じようにSDメモリカードのマウントができません。
SDメモリカードがマウントできない件を調査開始
いろいろと観察すると以下のようなことがわかりました。
- 2.6.32では問題なくSDメモリカードのマウントができる。
- 2.6.33では常にSDメモリカードのマウントが失敗する。再現率100%
再現が容易で、しかもうまくいく例もあるわけですからバグとしては比較的対処しやすい部類に入ります。私はSDメモリカードのファイルシステムやデバイスの制御に関して何の知識も持っていませんが、うまくいくパターンとうまくいかないパターンを比較していけばきっと原因までたどりつけるはずです。
まずは最も基本的なところでシリアルコンソールに出たログを比較してみます。
2.6.33のうまくいかないパターン。
mmc0: new SD card at address 0300 mmcblk0: mmc0:0300 SD512 488 MiB mmcblk0: unknown partition table
正常にマウントできる2.6.32のパターン。
mmc0: new SD card at address 0300 mmcblk0: mmc0:0300 SD512 488 MiB mmcblk0: p1
"unknown partition table"の周りを調べる
まずは"unknown partition table"でソースを検索すると、このメッセージは fs/partitions/check.c のcheck_partitionという関数で出していることがわかりました。
この関数にPARTNER-Jetでブレークポイントをかけて止めて、ステップ実行で動きを調べてみます。すると fs/partitions/msdos.c の化関数msdos_partitionが0を返すため、有効なパーティションが無いという判断になっていることがわかりました。
さらに関数msdos_partitionを調べるとセクターを読み出して、そのセクターの510バイト目がMSDOSのマジックナンバーと一致しないために、その関数から抜けてしまうことがわかりました。PARNER-Jetでその部分の周辺のメモリを見てみるとゼロが続いています。セクターのデータが正しく読めていないようです。
正常動作する2.6.32で同じところを追ってみると、関数msdos_partionで正しくpartitoinを認識していました。
つまり2.6.32と2.6.33の動作の違いはセクターが正しく読めているかどうかの違いということになります。ファイルシステムよりももっと下の層での動きを調べてみる必要があります。
MMCのデバッグモード
やはり怪しいのはこのボード用のMMCドライバです。drivers/mmc/host/a9tc_mmc.c
このソースを見るとdeb_dbgという関数でデバッグ用のログが出ることがわかりました。このデバッグログを有効にするためにmake menuconfigで以下の設定をします。
Device Drivers ---> MMC/SD/SDIO card support ---> [*] MMC debugging
さらにカーネルのログレベルを上げるため、カーネルのブートパラメータに
debug
を追加します。
2.6.32と2.6.33で同様の設定を行い、両者のログを比較しました。
2.6.32
... mmc0: new SD card at address 0300 mmc0: starting CMD16 arg 00000200 flags 00000095 a9tc_mmc a9tc_mmc.0: a9tc_mmc_cmd_done: CMD=16 RSP 900 mmc0: req done (CMD16): 0: 00000900 00000000 00000000 00000000 mmcblk0: mmc0:0300 SD512 488 MiB mmcblk0: mmc0: starting CMD18 arg 00000000 flags 000000b5 mmc0: blksz 512 blocks 8 flags 00000200 tsac 20 ms nsac 0 mmc0: CMD12 arg 00000000 flags 0000049d a9tc_mmc a9tc_mmc.0: MMC: DATA: size=512 num=8 flags=0x200 a9tc_mmc a9tc_mmc.0: a9tc_mmc_cmd_done: CMD=18 RSP 900 mmc0: req done (CMD18): 0: 00000900 00000000 00000000 00000000 mmc0: 4096 bytes transferred: 0 mmc0: (CMD12): 0: 00000000 00000000 00000000 00000000 p1 ...
2.6.33
... mmc0: new SD card at address 0300 mmc0: starting CMD16 arg 00000200 flags 00000095 a9tc_mmc a9tc_mmc.0: a9tc_mmc_cmd_done: CMD=16 RSP 900 mmc0: req done (CMD16): 0: 00000900 00000000 00000000 00000000 mmcblk0: mmc0:0300 SD512 488 MiB mmcblk0: mmc0: starting CMD18 arg 00000000 flags 000000b5 mmc0: blksz 512 blocks 8 flags 00000200 tsac 20 ms nsac 0 mmc0: CMD12 arg 00000000 flags 0000049d a9tc_mmc a9tc_mmc.0: MMC: DATA: size=512 num=8 flags=0x200 a9tc_mmc a9tc_mmc.0: a9tc_mmc_cmd_done: CMD=18 RSP 900 mmc0: req done (CMD18): 0: 00000900 00000000 00000000 00000000 mmc0: 4096 bytes transferred: 0 mmc0: (CMD12): 0: 00000000 00000000 00000000 00000000 unknown partition table ...
ログは長いので前後を省略していますが、このログを比較しても特に差はありませんでした。つまり、I/Oエラーが起きている形跡もなく、コマンドのシーケンスもタイミングも特に変わりがありません。
実際のセクターの読み込みはDMA転送で行われています。DMA転送の実装は arch/arm/mm/dma-mapping.c ですがこのあたりは2.6.32と2.6.33ではだいぶ異なっています。
DMA転送ではCPUのキャッシュをinvalidate(無効化:キャッシュのデータを捨ててもう一度メモリから読み直すようにする。)をする必要がありますが、この手順も2.6.32と2.6.33では異なるようです。
キャッシュをDisableにしてみる
試しにキャッシュ無しで動かしてみて様子を見ることにします。
まずは外堀を埋めるということでL2キャッシュを無効にしてみます。
make menuconfigで
System Type ---> A9TC platform type ---> [ ] ARM L2 cache Enable (マークをはずす) [ ] Enable the L2x0 outer cache controller (マークをはずす)
2.6.33をこれで動かしましたが、SDのmountについては依然として"unkown partition table"でした。
さらにL1のデータキャッシュを無効にしてみます。
make menuconfigで
System Type ---> [*] Disable D-Cache (C-bit)
これで2.6.33を動かすと、なんとSDメモリカードのmountに成功しました!
つまりこれで
- MMCのホストドライバはシロ
- DMA転送もシロ
- DMA転送時のキャッシュの制御がクロ
ということが判明しました。
ということで、今日のところはここまで。(続く)
関連するページ
Linux2.6.33を載せたKZM-CA9-01ボードでSDメモリカードがマウントできない(その2)