2013-01-31 17 views
6

Büyük bir DMA arabelleğini, yaklaşık 40 MB boyutunda ayırmak istiyorum. Ben dma_alloc_coherent() kullandığınızda, başarısız ve gördüğüm: Ben farklı değerler denedim ve dma_alloc_coherent() fazla 2^25 bayt (32 MB) tahsis edemez gibi görünüyorBüyük bir DMA arabelleğinin ayrıştırılması

------------[ 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 ]--- 

.

Böyle büyük bir DMA arabelleği nasıl dağıtılabilir?

+0

Büyük DMA tamponlar pahalıdır. Bellek bloğu, bitişik fiziksel bellek olmalıdır (bazı SPARC sistemlerinde olduğu gibi I/O için bir MMU yoksa) ve kilitlenmiş olmalıdır (sayfa hataları için daha yüksek öncelikli görevler için yer açmak üzere sayfalandırılamaz). Tipik bir çözüm, birden fazla DMA arabelleği kullanmak ve DMA zincirleme (aka dağılım/toplama) kullanmaktır. Gerçekten bir blokta 40MB aktarım yapan bir G/Ç işlemi var mı, yoksa gerçekten bir operasyon birikimi mi? – sawdust

+0

Üzerinde çalıştığım yazılımın kullanımı, özel bir donanım tarafından video yakalama ve görüntü işleme için büyük DMA arabellekleri gerektirir. Birkaç küçük arabellek kullanılarak yapılabilir, ancak zamanla parçalanma, arabelleklerin sorunlu hale getirilmesini ve yeniden tahsis edilmesini sağlar. İhtiyacım olan DMA arabelleklerinin boyutu ve miktarı sabittir, bu nedenle belleği önyüklemede bir kez ayırmak ve kullanıcı alanındaki bellek isteklerini yönetmek istiyorum. – miluz

+0

@miluz, bu sorunu çözdünüz mü? Nasıl ? – ransh

cevap

6

Sistem ön yüklemeden sonra dma_alloc_coherent() büyük ayırmalar için güvenilir olmayabilir. Bunun nedeni, hareketli olmayan sayfaların fiziksel belleğinizi hızlıca geniş bitişik aralıklarla nadiren doldurmasıdır. Bu uzun bir süre için bir sorun oldu.

Uygun bir yama seti size yardımcı olabilir, bu çekirdek 3.5'de görünen bitişik bellek ayırıcısıdır. Eğer bunun ile bir çekirdek kullanıyorsanız, çekirdek komut satırınızda cma=64M'u geçebilmeniz ve o kadar çok hafızanın saklanabileceğini (sadece hareketli sayfalar yerleştirilecektir). Daha sonra 40M tahsisinizi sorduğunuzda güvenilir bir şekilde başarılı olmalıdır. Simples!

fazla bilgi için bu LWN makaleye göz atın:

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

+0

Önyükleme zamanında belleği ayırmak benim için yeterli, bu yüzden memblock_alloc_base() ve memblock_remove() kullandım. Anlayışım için, bu işlevler, belleği çekirdeğe görünmez kılmalı ve yapmalı ve fiziksel adreslerde bitişik olmalı, dolayısıyla DMA için kullanılmasını iyi hale getirmelidir. – miluz

+0

Bunun işe yarayacağını düşünüyorum, ama dövülmüş pistten biraz uzak. Yükleyebileceğiniz ve kaldırabileceğiniz bir çekirdek modülü istiyorsanız da sorun yaşarsınız. – jleahy