将内存从一个内核模块映射到另一个模块中的DMA缓冲区

时间:2018-11-09 06:17:16

标签: c linux-kernel dma

我正在一个项目中,其中模块A 具有一个具有DMA内容的内存缓冲区,并调用模块B 的功能来执行DMA操作。简单起见,如下所示:

模块A:

void get_info()
{
    void *outBuffer = kmalloc(10);
    void *inBuffer = kmalloc(10);

    perform_dma(outBuffer);       // function from module B

    read_output(&inBuffer);      // function from module B
}

模块B:

void perform_dma(void *outBuffer)
{
    void *dma_buffer = dma_alloc_coherent()  // <-- allocate a new DMA buffer
    memcpy(dma_buffer, outBuffer, 10);

    do_dma();  // <-- after this is done, dma_buffer has the content module A needs.
}

void read_output(void **inBuffer)
{
    memcpy(*inBuffer, dma_buffer, 10);
}

我知道这可能不太有效,但是我无法更改 B模块,并且只能使用提供的API。在最佳情况下,我可以将 B perform_dma(void *outBuffer)原型更改为perform_dma(void **outBuffer)。它大部分时间都有效,但是在某种情况下(由于整个项目中涉及的所有中断/队列事件),我将无法显式调用read_output()并提供inBuffer来读取内容但只能将outBuffer地址发送到 B 后访问。

有没有一种方法可以将模块{em> A 中的outBuffer映射到模块 B 中分配的dma_buffer,以便能够读取输出从同一outBuffer返回?

1 个答案:

答案 0 :(得分:0)

我发现dma_map_single()/ dma_unmap_single()在我的情况下有效。根本不需要更改功能原型。只需在perform_dma()中使用dma_map_single(outBuffer ....,DMA_BIDIRECTIONAL)来获取总线地址并将其传递给dma控制器,这样在DMA完成后,outBuffer将从dma控制器返回内容。