Articles of dma

Linux DMA操作 – 如何启动传输

我已经阅读了Linux设备驱动程序LDD3 ,DMA-API.txt,DMA-HOWTO.txt也查看了驱动程序/ dma / dmatest.c,但我无法弄清楚如何启动dma传输。 所有关于映射内存的讨论都没有讨论如何启动事务。 PCI示例驱动程序具有传输function,但它使用“特定的”DMA操作,我试图找出一个更通用的/可移植的实现,而不是硬件依赖 我正在尝试做类似的事情 dma_map_single() 启动读/写事务 中断该事务已完成,使用处理程序或wait_event_freezable_timeout dma_unmap_single() 我只是读/写我映射的内存? 我如何注册callback处理程序? 编辑:给一点更多的细节,我在ARM平台上工作。

Linux的dma驱动程序dma_cap_set,dma_cap_zero

我正在为一个dma编写一个linux设备驱动程序,同时在LXR中通过dma驱动程序的源代码,我遇到了dma_cap_zero和dma_cap_set函数以及dma_cap_ *的整个系列。 这些function是什么? 还有一个称为dma_transaction_type的结构 enum dma_transaction_type { DMA_MEMCPY, DMA_XOR, DMA_PQ, DMA_XOR_VAL, DMA_PQ_VAL, DMA_MEMSET, DMA_INTERRUPT, DMA_SG, DMA_PRIVATE, DMA_ASYNC_TX, DMA_SLAVE, DMA_CYCLIC, DMA_INTERLEAVE, /* last transaction type for creation of the capabilities mask */ DMA_TX_TYPE_END, }; 枚举types代表什么?

通过PCIe的DMA到其他设备

我试图直接从Linux中的另一个PCIe设备访问NIC中的DMA地址。 具体来说,我试图从NVIDIA GPU读取,以绕过所有的CPU。 我已经研究了零拷贝networking和DMA到用户空间的post,但是他们要么没有回答这个问题,要么涉及到从内核空间到用户空间的一些拷贝。 我试图避免使用任何CPU时钟,因为与延迟不一致,并且我有非常严格的延迟要求。 我拿到了我使用的intel卡(e1000e驱动程序)的NIC驱动程序,我发现在哪里分配了环形缓冲区。 正如我在前面的文章中所理解的那样,我会对dma_addr_ttypes的描述符感兴趣。 他们也有一个叫做dma的rx_ring结构体的成员。 我使用ioctl调用来传递desc和dma成员,但除了零之外,我无法在GPU中获得任何东西。 GPU代码如下: int *setup_gpu_dma(u64 addr) { // Allocate GPU memory int *gpu_ptr; cudaMalloc((void **) &gpu_ptr, MEM_SIZE); // Allocate memory in user space to read the stuff back int *h_data; cudaMallocHost((void **)&h_data, MEM_SIZE); // Present FPGA memory to CUDA as CPU locked pages int error = cudaHostRegister((void **) […]

Linux DMA API:指定地址增量行为?

我正在为Altera Soc开发工具包编写一个驱动程序,并且需要支持两种数据传输模式: FIFO传输 :写入(或读取)FPGA FIFO时,目标(或源)地址不能由DMA控制器增加。 非FIFO传输 :这是正常的(类似RAM的)传输,源地址和目的地址都需要传输每个字的增量。 我使用的特定DMA控制器是CoreLink DMA-330 DMA控制器,其Linux驱动程序是pl330.c(drivers / dma / pl330.c)。 这个DMA控制器确实提供了在“固定地址突发”和“增量地址突发”(这些与我的“FIFO传输”和“非FIFO传输”同义)之间切换的机制。 pl330驱动程序通过设置CCRn寄存器中的相应位来指定它想要的行为 #define CC_SRCINC (1 << 0) #define CC_DSTINC (1 << 14) 我的问题 : 我不太清楚pl330(例如我的驱动程序)的客户应该如何指定地址递增行为。 DMA引擎客户端API没有提到如何指定这一点,而DMA引擎提供者API只是简单说明: 指向RAM的地址通常在每次传输后递增(或递减)。 如果是环形缓冲区,它们可能会循环(DMA_CYCLIC)。 指向设备寄存器(例如FIFO)的地址通常是固定的。 没有详细说明如何将地址types传递给提供者(在我的情况下是pl300驱动程序)。 在pl330_prep_slave_sg方法中: if (direction == DMA_MEM_TO_DEV) { desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; desc->req.rqtype = MEMTODEV; fill_px(&desc->px, addr, sg_dma_address(sg), sg_dma_len(sg)); } else […]

如何通过DMA将数据从RAM传输到RAM?

我想写一个内核模块,可以通过DMA从RAM传输数据到RAM。 有一些文章讨论这个,但我真的不明白。 有人说可能有人说这不是。 如果我理解了ldd3,那么RAM到RAM的拷贝是不可能的,但是驱动程序/dma/dmaengine.c提供了一个标志DMA_MEMCPY用于“DMA传输types”,所以应该有一个办法。 这是否正确,我可以使用dma引擎将数据从一个ram地址传输到另一个吗? 如果是硬件相关的,我怎样才能确定我的系统是否支持dma memcpy?

DMA引擎和DMA控制器有什么区别?

如上所述,dma引擎和dma控制器(关注linux)有什么区别? linux dma引擎什么时候到位? 这是一个特殊的设备,还是所有外围设备的一部分,它支持dma? 浏览linux源码时,我发现了驱动程序ste_dma40.c。 任何驱动程序如何使用此引擎?

在ARM i.MX287上增加Linux DMA_ZONE内存

我正在使用2.6.35.3内核的embedded式Linux系统。 在设备内部,我们需要一个4MB + 192kB连续的DMAcaching器用于我们的数据采集驱动器之一。 驱动程序使用SPI传输将数据复制到此缓冲区。 用户空间应用程序发出一个mmap系统调用,将缓冲区映射到用户空间,然后直接读取可用数据。 使用“alloc_bootmem_low_pages”调用来分配缓冲区,因为使用其他方法(如kmalloc)不可能分配超过4 MB的缓冲区。 但是,由于最近的升级,我们需要增加缓冲空间到22MB + 192kB。 据我所知,Linux内核只有16MB的DMA内存。 因此,理论上这是不可能的,除非有办法调整这个设置。 如果有谁知道如何执行此操作,请让我知道? 这是一个好主意,还是会使系统不稳定?

在linux的sk_buff中,skb-> data是物理地址还是虚拟地址?

我正在调查embedded式系统的以太网驱动程序中的一些内存损坏问题。 我怀疑总线主控DMA控制器和慢速SDRAM之间的问题。 所以我想在快速SRAM中使用反弹缓冲器。 为此,我需要两件事:我必须将SRAM的物理地址(从总线主设备的angular度来看)放到DMA控制器缓冲区描述符中,一旦DMA控制器报告一个数据,我必须将数据从反弹缓冲区存入SDRAM的sk_buff传入数据包。 从阅读中我无法确定 http://vger.kernel.org/~davem/skb.html http://vger.kernel.org/~davem/skb_data.html 是skb-> data是一个物理地址还是虚拟地址。 即我应该打电话 memcpy(skb->data, phys_to_virt(bounce_addr), len); 要么 memcpy(phys_to_virt(skb->data), phys_to_virt(bounce_addr), len); 把数据包放到sk_buff中,这样linuxnetworking堆栈的其余部分就可以处理它了? 编辑: 这是有问题的驱动程序 。 我会说,它是通过虚拟地址到DMA控制器寄存器,因此无法正常工作,但我有这个代码工作的开发工具包。 然而,我的SDRAM没有像开发工具DDR SDRAM那么好的时序,所以我正在考虑实现反弹缓冲器。

从用户空间创build物理内存以用于DMA传输

我想创build一些内存用于DMA传输。 (使用Linux 2.6.18-128.el5#1 SMP) 我有一个API堆栈+内核驱动程序可以为我做这个H / W,但它非常非常慢! 如果我使用API​​来创buildDMA传输,它会在系统RAM中分配一些非常高的内存(例如一次运行0x7373a6f8)。 (我有设备的ICD,所以有一个内存映射mmap'd,这是我怎么能find这个地址了,最后我想SET到我自己的地址,因此/ dev / mem在下面的地图中) 我似乎无法绕过这个高地址来映射内存,大概是因为它超出了我的虚拟内存空间而被内核阻塞了。 我希望能够做的是使用(地图)这个地址,所以我可以读/写,或创build我自己的物理内存,我可以读/写。 # cat /proc/iomem 00000000-0009fbff : System RAM 00000000-00000000 : Crash kernel 000a0000-000bffff : Video RAM area 000c0000-000c7fff : Video ROM 000f0000-000fffff : System ROM 00100000-7fd64fff : System RAM # Is this all of /dev/mem? 00400000-00612916 : Kernel code 00612917-006ef9db : Kernel […]

为Linux 2.6.30 DMA API映射设备内存

我一直在努力与这一个,真的很感谢一些帮助。 我想使用我的At91sam9g45的内部SRAM(垫脚石 – 开机后不使用)来加速一些密集的计算,并遇到满足以下所有条件的麻烦: 内存可以从用户空间访问。 这很容易使用用户空间mmap() ,然后使用内核remap_pfn_range() 。 使用返回的指针,我的用户空间程序可以读/写SRAM。 使用内核DMA API调用dma_async_memcpy_buf_to_buf()使用DMA来执行memcpy。 在我的基本驱动程序中,我想调用这个操作来将DDR中的数据(用kmalloc()分配)复制到SRAM缓冲区中。 所以我的问题是我有用户空间和物理地址,但没有内核空间DMA API友好的映射。 我试过使用ioremap并使用提供给iotable_init()的固定的iotable_init()地址。 这些似乎都没有导致一个内核虚拟地址,可以使用像virt_to_bus (这对kmalloc地址,我认为是在DMA API中使用)的东西。 有办法,那只是手动使用物理地址触发DMA,但我想尝试解决这个问题。 我一直在阅读LDD3和谷歌search,但我看不到任何使用非kmalloc内存的DMA API(PCI总线除外)的例子。