免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 21872 | 回复: 34

有关dma映射的问题 [复制链接]

论坛徽章:
0
发表于 2008-03-18 19:31 |显示全部楼层
就像这几天发的贴子所讨论的那样 我打算在内存中分配一块dma缓存并映射到用户空间去  但当到具体实现的时候 我发现又来了一个问题
我首先看了下8139  它分配dma是通过pci_alloc_consistent 函数   这里面先是使用get_free_pages分配了空间  然后用类pci_map_single的函数建立了一个流式映射   我仔细的又把ldd3第15章看了遍(我发现ldd3第15章是所有章节里面最tmd有嚼头的。。。我几乎就是在反复的看它)
上面指出 当一个缓冲区被流式映射 只有将其unmap掉后  驱动才能安全的访问里面的数据内容  里面这样描述:一旦缓冲区被映射 它将属于设备而不是处理器 知道缓冲区被取消映射前 驱动程序不能以任何方式访问其中的内容。。。。这条规则意味着,在包含了所有要写入的数据之前,不能映射要写入的设备缓冲区
问题是dma缓冲区是一直有数据的  是不是无法执行unmap操作   那么我将怎么把它映射到用户空间呢

[ 本帖最后由 duanius 于 2008-3-18 19:41 编辑 ]

论坛徽章:
0
发表于 2008-03-18 19:40 |显示全部楼层
我开始以为就是申请一块物理地址连续的内存  把地址传给网卡 同时映射到用户空间
没想到居然还有不能映射的可能。。。我还以为这块缓冲区驱动和网卡是可以同时访问的
我理解有错么 。。。

论坛徽章:
0
发表于 2008-03-18 20:33 |显示全部楼层
一开始分析源码我想pci_alloc_consistent其实只做了两件事  一是分配页面  二是得到页面始值的物理地址  然后我想其实自己就可以实现   (在网上查了查文章也说在X86架构下pci_map_single函数就是简单的返回物理地址 没其他操作)但是在深入的看源码的时候我发现pci_map_single这个函数还是做了些文章  从ldd3和代码注释中可以看出当pci_alloc_consistent调用pci_map_single_l的时候建立了流式映射  但问题在于  但我查了下DMA-mapping文档 (ldd3也是如此)说pci_alloc_consistent建立的是一致性映射  而且网卡dma映射环就应该建立一致性而不是流式dma映射  。。。
i am totally confused...  既然pci_alloc_consistent建立的是一致性dma映射 那为啥源码里面(pci_iommu.c)里面却在pci_alloc_consistent的定义中调用了建立流式映射的pci_map_single_l
8139的dma环到底实在哪种映射下工作的?

论坛徽章:
0
发表于 2008-03-18 22:39 |显示全部楼层
在pci_map_single之后,只是获得一个地址,在写寄存器以后才通知网卡向该地址DMA数据.
当网卡将rx_desc和实际的skb.data DMA到主存以后才产生中断.这时候通过rx_desc的标志位来判断有多少包就可以了.

ring_desc是一致性映射,而skb.data是流映射,因为需要随时map和unmap.

论坛徽章:
0
发表于 2008-03-18 22:53 |显示全部楼层
能具体讲解下么  我疑惑的地方是pci_alloc_consistent这个函数本事是用做一致性dma映射用的
但函数的实现在分配内存后对这个内存调用的却是pci_map_single_1  这个函数建立的流dma映射
所以我就糊涂了    那pci_alloc_consistent建立的dma内存到底是流式的还是一致性的呢
这个dma内存能不能mmap到用户空间内进行用户态读取呢?

论坛徽章:
0
发表于 2008-03-18 23:00 |显示全部楼层
8139的驱动没看过,不过应该是对rx_desc中的buff指针进行的pci_map_single

这块区域pci_unmap_single之后爱怎么使就怎么使

论坛徽章:
0
发表于 2008-03-19 10:26 |显示全部楼层
>> 那pci_alloc_consistent建立的dma内存到底是流式的还是一致性的呢
肯定是一致的, 从名字就能看出来。

Documentation/DMA-mapping.txt文件专门讲解了为什么需要 consistent和 streaming, 以及如何使用,值得一看 (应该比ldd3好)

论坛徽章:
0
发表于 2008-03-19 12:23 |显示全部楼层
事实上我昨天就仔细的看了下DMA-mapping.txt这篇文档  今天又重看了下  这篇文章确实写的很好  补充了很多ldd3没点到的地方  不过这一切对解答我的疑惑没有什么帮助
我知道是我理解不够  所以出现了一些看上去自相矛盾的地方
这是pci_alloc_consistent在pci_iommu.c中的源码:
/* Allocate and map kernel buffer using consistent mode DMA for PCI
   device.  Returns non-NULL cpu-view pointer to the buffer if
   successful and sets *DMA_ADDRP to the pci side dma address as well,
   else DMA_ADDRP is undefined.  */

void *
pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
{
        void *cpu_addr;
        long order = get_order(size);
        gfp_t gfp = GFP_ATOMIC;

try_again:
        cpu_addr = (void *)__get_free_pages(gfp, order);
        if (! cpu_addr) {
                printk(KERN_INFO "pci_alloc_consistent: "
                       "get_free_pages failed from %p\n",
                        __builtin_return_address(0));
                /* ??? Really atomic allocation?  Otherwise we could play
                   with vmalloc and sg if we can't find contiguous memory.  */
                return NULL;
        }
        memset(cpu_addr, 0, size);

        *dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
        if (*dma_addrp == 0) {
                free_pages((unsigned long)cpu_addr, order);
                if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
                        return NULL;
                /* The address doesn't fit required mask and we
                   do not have iommu. Try again with GFP_DMA. */
                gfp |= GFP_DMA;
                goto try_again;
        }
               
        DBGA2("pci_alloc_consistent: %lx -> [%p,%x] from %p\n",
              size, cpu_addr, *dma_addrp, __builtin_return_address(0));

        return cpu_addr;
}
代码很简单  第一部分就是分配内存 直到分配成功为止   而第二部分就是调用pci_map_single_1建立dma映射    同样在这个文件里  有有关pci_map_single_1的说明:
/* Map a single buffer of the indicated size for PCI DMA in streaming
   mode.  The 32-bit PCI bus mastering address to use is returned.
   Once the device is given the dma address, the device owns this memory
   until either pci_unmap_single or pci_dma_sync_single is performed.  */

static dma_addr_t
pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
                 int dac_allowed)

不明白既然是一致性  为啥里面建立映射调用的是建立流模式的函数  这是让我搞不懂的地方
也许奥秘就在pci_map_single_1 具体实现里  不过我不大看的懂。。。

[ 本帖最后由 duanius 于 2008-3-19 12:24 编辑 ]

论坛徽章:
0
发表于 2008-03-19 12:40 |显示全部楼层
原帖由 terryfe 于 2008-3-18 23:00 发表
8139的驱动没看过,不过应该是对rx_desc中的buff指针进行的pci_map_single

这块区域pci_unmap_single之后爱怎么使就怎么使

你的意思我不是很理解  是不是说整个dma缓冲区一致性映射   而具体的有包在执行dma操作的那块缓冲单元执行流映射。。
这样就是整体一致    细节上在操作的执行流  这样就解释了为什么pci_alloc_consistent  里面调用pci_map_single_1?
我瞎猜的。。。。

论坛徽章:
0
发表于 2008-03-19 12:41 |显示全部楼层

回复 #8 duanius 的帖子

你看的是哪个版本?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP