swiotlb和smmu区别在map page这个函数

来源:互联网 发布:js需要做保护层吗 编辑:程序博客网 时间:2024/06/05 15:33
swiotlb和smmu最大的区别在map page这个函数,前面分析过smmu的map page函数会自建页表也映射iova和pa之间的映射。我们下面看看swiotlb的的map page
static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
                     unsigned long offset, size_t size,
                     enum dma_data_direction dir,
                     unsigned long attrs)
{
    dma_addr_t dev_addr;

    dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs);
    if (!is_device_dma_coherent(dev))
        __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);

    return dev_addr;
}
由于我们用的是coherent,所以if (!is_device_dma_coherent(dev)) 这个条件不成来,直接调用swiotlb_map_page 将page 转换成hw用的dma address。
dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
                unsigned long offset, size_t size,
                enum dma_data_direction dir,
                unsigned long attrs)
{
    phys_addr_t map, phys = page_to_phys(page) + offset;
    dma_addr_t dev_addr = phys_to_dma(dev, phys);

    BUG_ON(dir == DMA_NONE);
    /*
     * If the address happens to be in the device's DMA window,
     * we can safely return the device addr and not worry about bounce
     * buffering it.
     */
    if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
        return dev_addr;

    trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);

    /* Oh well, have to allocate and map a bounce buffer. */
    map = map_single(dev, phys, size, dir);
    if (map == SWIOTLB_MAP_ERROR) {
        swiotlb_full(dev, size, dir, 1);
        return phys_to_dma(dev, io_tlb_overflow_buffer);
    }

    dev_addr = phys_to_dma(dev, map);

    /* Ensure that the address returned is DMA'ble */
    if (!dma_capable(dev, dev_addr, size)) {
        swiotlb_tbl_unmap_single(dev, map, size, dir);
        return phys_to_dma(dev, io_tlb_overflow_buffer);
    }

    return dev_addr;
}

在swiotlb_map_page 中如果要map的page 在dma 的capable之内的话,就直接返回page对应的物理地址
if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
        return dev_addr;
dma_capable 就是看要映射的page 的address是否在mask 返回内,一般情况下kernel中dma_mask 一般是4G,也就是说map的page的address在4G范围内,采用swiotlb的方式得到的dma adress和 page对应的物理地址是一样的.
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
    if (!dev->dma_mask)
        return false;

    return addr + size - 1 <= *dev->dma_mask;
}
如果超过4G就要用boundle buffer转一下.

0 0
原创粉丝点击