2013-01-31 109 views
6

サイズが約40 MBの大きなDMAバッファを割り当てたい。私はdma_alloc_coherent()を使用する場合、それは失敗し、私が見ることは次のとおりです。大きなDMAバッファの割り当て

------------[ cut here ]------------ 
WARNING: at mm/page_alloc.c:2106 __alloc_pages_nodemask+0x1dc/0x788() 
Modules linked in: 
[<8004799c>] (unwind_backtrace+0x0/0xf8) from [<80078ae4>] (warn_slowpath_common+0x4c/0x64) 
[<80078ae4>] (warn_slowpath_common+0x4c/0x64) from [<80078b18>] (warn_slowpath_null+0x1c/0x24) 
[<80078b18>] (warn_slowpath_null+0x1c/0x24) from [<800dfbd0>] (__alloc_pages_nodemask+0x1dc/0x788) 
[<800dfbd0>] (__alloc_pages_nodemask+0x1dc/0x788) from [<8004a880>] (__dma_alloc+0xa4/0x2fc) 
[<8004a880>] (__dma_alloc+0xa4/0x2fc) from [<8004b0b4>] (dma_alloc_coherent+0x54/0x60) 
[<8004b0b4>] (dma_alloc_coherent+0x54/0x60) from [<803ced70>] (mxc_ipu_ioctl+0x270/0x3ec) 
[<803ced70>] (mxc_ipu_ioctl+0x270/0x3ec) from [<80123b78>] (do_vfs_ioctl+0x80/0x54c) 
[<80123b78>] (do_vfs_ioctl+0x80/0x54c) from [<8012407c>] (sys_ioctl+0x38/0x5c) 
[<8012407c>] (sys_ioctl+0x38/0x5c) from [<80041f80>] (ret_fast_syscall+0x0/0x30) 
---[ end trace 4e0c10ffc7ffc0d8 ]--- 

私は別の値を試してみたとdma_alloc_coherent()以上2^25バイト(32 MB)を割り当てることができないように見えます。

どのように大きなDMAバッファを割り当てることができますか?

+0

大DMAバッファは高価です。メモリブロックは、(一部のSPARCシステムの場合のようにI/O用のMMUがない限り)連続した物理メモリでなければならず、ロックされています(プライオリティの高いタスクでページ違反のためにスペースを空けることはできません)。一般的な回避策は、複数のDMAバッファを使用し、DMAチェーン(散漫/ギャザーとも呼ばれます)を利用することです。あなたは本当に1ブロックで40MBを転送するI/O操作を持っていますか?これは本当に操作の蓄積ですか? – sawdust

+0

私が取り組んでいるソフトウェアの使用例では、専用のハードウェアによるビデオキャプチャと画像処理のために大きなDMAバッファが必要です。それはいくつかのより小さいバッファを使用することによって行うことができますが、時間の経過とともにフラグメンテーションはバッファの解放と再割り当てを問題にします。私が必要とするDMAバッファのサイズと量は固定されているので、ブート時に一度メモリを割り当て、ユーザ空間でメモリ要求を管理したい。 – miluz

+0

@ミルズ、この問題を解決しましたか?どうやって ? – ransh

答えて

6

システム起動後、dma_alloc_coherent()は大きな割り当てでは必ずしも信頼できるものではありません。これは、移動不可能なページがすばやく物理メモリをいっぱいにして、まれに大きな連続した範囲を作成するためです。これは長い間問題でした。

便利なことに、最近のパッチセットが役に立ちます。これは、カーネル3.5に登場した連続したメモリアロケータです。これでカーネルを使用している場合は、カーネルのコマンドラインにcma=64Mを渡すことができ、その多くのメモリが予約されます(移動可能なページだけがそこに置かれます)。その後40Mの割り当てを求めると、それは確実に成功するはずです。シンプルズ!

詳細については、このLWNの記事をチェックアウト:

https://lwn.net/Articles/486301/

+0

ブート時にメモリを割り当てることは私にとっては十分です。だから私はmemblock_alloc_base()とmemblock_remove()を使いました。私の理解では、これらの関数は、カーネルにメモリを割り当てずに物理アドレスに連続しているため、DMAに使用するのに適しています。 – miluz

+0

私はそれはうまくいくはずだと思うけど、それはちょっとした暴れからです。ロードしたりアンロードしたりできるカーネルモジュールが必要な場合は、問題が発生します。 – jleahy

関連する問題