(以下應該算是讀書心得 與 我自己的想法,並不是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?
沒有留言:
張貼留言