2013-01-31 22 views
6

Tôi muốn cấp bộ đệm DMA lớn, có kích thước khoảng 40 MB. Khi tôi sử dụng dma_alloc_coherent(), nó không thành công và những gì tôi thấy là:Phân bổ bộ đệm DMA lớn

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

Tôi đã thử giá trị khác nhau và có vẻ như dma_alloc_coherent() không thể phân bổ nhiều hơn 2^25 byte (32 MB).

Làm cách nào để có thể phân bổ bộ đệm DMA lớn?

+0

đệm DMA lớn là tốn kém. Khối bộ nhớ phải là bộ nhớ vật lý liền kề (trừ khi có một MMU cho I/O như trong một số hệ thống SPARC) và bị khóa (không thể được tạo ra để tạo không gian cho các lỗi trang do các tác vụ có mức ưu tiên cao hơn). Cách giải quyết điển hình là sử dụng nhiều bộ đệm DMA và sử dụng chuỗi DMA (còn gọi là phân tán/thu thập). Bạn có thực sự có một hoạt động I/O chuyển 40MB trong một khối, hay đây thực sự là một sự tích lũy các hoạt động? – sawdust

+0

Trường hợp sử dụng phần mềm mà tôi đang thực hiện yêu cầu bộ đệm DMA lớn để quay video và xử lý hình ảnh bằng phần cứng chuyên dụng. Nó có thể được thực hiện bằng cách sử dụng một số bộ đệm nhỏ hơn, nhưng theo thời gian phân mảnh làm cho giải phóng và tái phân bổ các bộ đệm có vấn đề. Kích thước và số lượng bộ đệm DMA tôi cần là cố định, vì vậy tôi muốn cấp phát bộ nhớ một lần khi khởi động và quản lý các yêu cầu bộ nhớ trong không gian người dùng. – miluz

+0

@miluz, bạn có giải quyết vấn đề này không? làm sao ? – ransh

Trả lời

6

Sau khi hệ thống đã khởi động dma_alloc_coherent() không nhất thiết phải đáng tin cậy cho phân bổ lớn. Điều này đơn giản chỉ vì các trang không thể di chuyển nhanh chóng lấp đầy bộ nhớ vật lý của bạn làm cho phạm vi tiếp giáp lớn hiếm gặp. Đây là một vấn đề trong một thời gian dài.

Một bộ vá gần đây có thể giúp bạn, đây là bộ cấp phát bộ nhớ tiếp giáp xuất hiện trong kernel 3.5. Nếu bạn đang sử dụng một hạt nhân với điều này thì bạn sẽ có thể vượt qua cma=64M trên dòng lệnh hạt nhân của bạn và nhiều bộ nhớ sẽ được dành riêng (chỉ các trang di chuyển sẽ được đặt ở đó). Khi bạn yêu cầu phân bổ 40 triệu của bạn, nó sẽ thành công đáng tin cậy. Các mẫu!

Để biết thêm thông tin kiểm tra bài viết LWN này:

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

+0

Phân bổ bộ nhớ lúc khởi động đủ tốt cho tôi, vì vậy tôi đã sử dụng memblock_alloc_base() và memblock_remove(). Theo hiểu biết của tôi, các chức năng này sẽ phân bổ và làm cho bộ nhớ ẩn với hạt nhân và nó tiếp giáp trong các địa chỉ vật lý, do đó làm cho nó tốt được sử dụng cho DMA. – miluz

+0

Tôi nghĩ rằng nên làm việc, nhưng đó là một chút tắt theo dõi bị đánh đập. Bạn cũng sẽ gặp khó khăn nếu bạn muốn có một mô-đun hạt nhân mà bạn có thể tải và dỡ bỏ. – jleahy