设备驱动里一般调用dma_map_single()/dma_unmap_single()处理cache。调用dma_map_single函数时需要指定DMA的方向,DMA_TO_DEVICE或者DMA_FROM_DEVICE。Linux会根据direction的值invalidate或者clean cache。 drivers\net\ethernet\cadence\macb_main.c的函数macb_tx_map()里,调用dma_map_single()刷新cache,macb_tx_...
在一些简单的系统中,设备可以直接对物理地址 Y 进行 DMA。但在许多其他系统中,有 IOMMU 硬件将 DMA 地址转换为物理地址,例如,它将 Z 转换为 Y。这是 DMA 的部分原因API:驱动程序可以将虚拟地址 X 提供给 dma_map_single() 之类的接口,该接口设置任何所需的 IOMMU 映射并返回 DMA 地址 Z。然后驱动程序告诉...
dma to device时,需要将cache中的数据flush到memory中; dma from device时,需要先将cache中的数据invalidate掉,避免CPU读取的是原来的数据; dma_map_single函数如下: map操作时存在两种方式,直接映射或使用iommu来完成映射; dma_unmap_single是逆操作: 从上述函数中可以看到,最终都会调用到arch相关的cache操作,这个与...
与dma_alloc_coherent()一样,这将返回两个值:CPU可用的地址和池设备可用的DMA地址。 void dma_pool_free(structdma_pool *pool,void*vaddr, dma_addr_taddr) 将内存放回池中。池是传递给dma_pool_alloc()的内容;CPU(vaddr)和DMA地址是该例程分配的内存被释放时返回的内容。 void dma_pool_destroy(structd...
二是一旦缓冲区被映射,它将属于设备,不是处理器。直到缓冲区被撤销映射前,驱动程序不能以任何方式访问其中的内容。只用当dma_unmap_single函数被调用后,显示刷新处理器缓存中的数据,驱动程序才能安全访问其中的内容。 三是在DMA出于活动期间内,不能撤销对缓冲区的映射,否则会严重破坏系统的稳定性。
在Linux中,可以使用dma_map_single()函数将物理地址映射到虚拟地址。使用完成后,可以使用dma_unmap_single()函数来取消映射。 总之,Linux DMA使用技巧包括使用合适的DMA缓冲区,设置传输标志,选择合适的DMA引擎,处理中断和回调,控制传输的优先级,以及进行内存映射等。通过合理使用这些技巧,可以提高DMA传输的效率和性能,...
drivers\net\ethernet\cadence\macb_main.c的函数macb_tx_map()里,调用dma_map_single()刷新cache,macb_tx_interrupt()的macb_tx_unmap()再调用dma_unmap_single()。 代码简化后如下: macb_tx_map( ) { ... mapping = dma_map_single(&bp->pdev->dev, skb->...
dma_addr_t dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction direction); (3)当传输完毕后,使用dma_unmap_single删除映射: dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction); ...
The implementation of dma_map_single() and dma_unmap_single() is exactly the same for all the architectures that support them. Factor them out to <linux/dma-mapping.h>, and make all drivers to include <linux/dma-mapping.h> instead of <asm/dma-mapping.h>. If we need to differentiate...
dma_unmap_len_set(tx_buffer, len, 0); // clear last DMA location and unmap remaining buffers */ while (tx_desc != eop_desc) { } } 无非就是清理了 skb,解除了 DMA 映射等等。到了这一步,传输才算是基本完成了。 为啥我说是基本完成,而不是全部完成了呢?因为传输层需要保证可靠性,所以 skb...