2013-01-31 3 views
6

크기가 약 40MB 인 대형 DMA 버퍼를 할당하려고합니다. 내가 dma_alloc_coherent()를 사용하는 경우, 그것은 실패하고 내가 보는 것은 : 내가 다른 값을 시도하고 dma_alloc_coherent() 이상 2^25 바이트 (32메가바이트)를 할당 할 수없는 것 같습니다큰 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 버퍼를 할당 할 수 있습니까?

+0

큰 DMA 버퍼가 비싸다. 메모리 블록은 인접한 물리적 메모리 (일부 SPARC 시스템에서와 같이 I/O 용 MMU가없는 경우) 및 잠겨 있습니다 (우선 순위가 높은 작업에 의해 페이지 폴트를위한 공간을 만들기 위해 페이징 할 수 없음). 일반적인 해결 방법은 둘 이상의 DMA 버퍼를 사용하고 DMA 체인 (일명 scatter/gather)을 이용하는 것입니다. 한 블록에 40MB를 전송하는 I/O 연산이 실제로 있습니까? 아니면 실제로 연산의 누적입니까? – sawdust

+0

제가 작업하고있는 소프트웨어의 사용 사례는 특수한 하드웨어로 비디오 캡쳐 및 이미지 처리를 위해 대형 DMA 버퍼가 필요합니다. 여러 개의 작은 버퍼를 사용하여 수행 할 수 있지만 시간이 지남에 따라 조각화는 버퍼를 해제하고 버퍼를 문제가있는 것으로 다시 할당합니다. 필요한 크기와 양의 DMA 버퍼가 고정되어 있으므로 부팅 할 때 메모리를 한 번 할당하고 사용자 공간에서 메모리 요청을 관리하려고합니다. – miluz

+0

@miluz,이 문제를 해결 했습니까? 어떻게? – ransh

답변

6

시스템이 부팅 된 후 dma_alloc_coherent()은 큰 할당에 대해 반드시 신뢰할 수있는 것은 아닙니다. 이것은 단순히 이동 불가능한 페이지가 실제 메모리를 빠르게 채워서 드문 큰 연속 범위를 만들기 때문입니다. 이것은 오랫동안 문제였습니다.

편리한 패치 세트가 도움이 될 수 있습니다. 이것은 커널 3.5에 등장한 연속 메모리 할당 기입니다. 이 경우 커널을 사용하고 있다면 커널 명령 행에 cma=64M을 넘겨 줄 수 있어야하며 많은 메모리가 예약 될 것입니다 (오직 이동 가능한 페이지 만이 그곳에 위치 할 것입니다). 이후 40M 할당을 요청하면 안정적으로 성공해야합니다. Simples!

자세한 내용은이 LWN 문서를 체크 아웃 :

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

+0

부팅 할 때 메모리를 할당하는 것이 충분하기 때문에 memblock_alloc_base()와 memblock_remove()를 사용했습니다. 필자의 이해를 돕기 위해이 함수는 커널에 메모리를 보이지 않도록 할당해야하며 물리적 주소에서는 연속적이므로 DMA 용으로 사용하는 것이 좋습니다. – miluz

+0

나는 그것이 효과가 있다고 생각하지만, 조금 두들겨 패다. 로드 및 언로드 할 수있는 커널 모듈을 원한다면 문제가 발생할 수도 있습니다. – jleahy