2009年11月30日 星期一

Streaming DMA mappings

(以下應該算是讀書心得 與 我自己的想法,並不是Linux的實際行為,例如ARM就不完全這樣做,讓我很搞不懂到底是我理解錯了,還是ARM Linux的問題...)

Linux Device Driver, 3rd ed, Chapter 15: Memory Mapping and DMA

dma_map_single/dma_unmap_single: setup/undo transfer buffer for device DMA.
dma_sync_single_for_cpu/dma_sync_single_for_device: for temporarily uses of the buffer

主要是用來解決下面兩個問題:
cache coherence(CC): Cache與memory內容可能不一致。cpu給device的資料可能在cache中,則device可能會讀到memory上的舊資料;或 device已經改變memory了,但cpu卻讀到cache的舊資料
bounce buffer(BB): 可能因為某些原因,若device無法用所給的buffer address做DMA時,這個時候需要另外allocate一塊buffer取代原來的buffer做DMA,把原buffer的資料搬到新buffer上,完成後再把資料搬回去。

資料流的方向:
DMA_TO_DEVICE
DMA開始前,BB需要把原buffer copy 到新buffer;CC要"clean"(writeback) cache to memory
(dma_map_single, dma_sync_single_for_device)

DMA_FROM_DEVICE
DMA結束後,CC要invalidate cache;BB要把新buffer內DMA的結果copy到原buffer上
(dma_unmap_single, dma_sync_single_for_cpu)

DMA_BIDIRECTION
DMA開始前,BB需要把原buffer copy 到新buffer;CC要"clean"(writeback) cache to memory
DMA結束後,CC要invalidate cache;BB要把新buffer內DMA的結果copy到原buffer上
但實際上kernel會做"flush" cache -- writeback and invalidate
DMA開始前,BB需要把原buffer copy 到新buffer;CC要flush cache
DMA結束後,BB要把新buffer內DMA的結果copy到原buffer上

dma_map_single/dma_unmap_single可以用flush,但是dma_sync_single_for_device和dma_sync_single_for_cpu則不應該用flush

dma_sync_single_for_cpu
buffer要給CPU使用前,CC要invalidate cache;BB要把新buffer內DMA的結果copy到原buffer上

dma_sync_single_for_device
buffer還給device DMA前,BB需要把原buffer copy 到新buffer;CC要"clean"(writeback) cache to memory

用這四個function去區隔出CPU access與device access的時間



Linux Device Driver, 3rd ed, Chapter 15: Memory Mapping and DMA, page 445.

Bounce buffers are created when a driver attempts to perform DMA on an address that is not reachable by the peripheral device - a high-memory address, for example.
How about address not aligned as device required?

沒有留言: