当在code中调用dma_mmap_coherent时,这是个宏
#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
在dma_mmap_attrs 中又会掉用get_dma_ops 来得到dma的ops
static inline int
dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
           dma_addr_t dma_addr, size_t size, unsigned long attrs)
{
    struct dma_map_ops *ops = get_dma_ops(dev);
    BUG_ON(!ops);
    if (ops->mmap)
        return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
    return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
}
get_dma_ops 的实现如下:
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
    if (xen_initial_domain())
        return xen_dma_ops;
    else
        return __generic_dma_ops(dev);
}
在arm64中xen_initial_domain() 肯定是返回false的,因此继续看__generic_dma_ops
static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
{
    if (dev && dev->archdata.dma_ops)
        return dev->archdata.dma_ops;

    /*
     * We expect no ISA devices, and all other DMA masters are expected to
     * have someone call arch_setup_dma_ops at device creation time.
     */
    return &dummy_dma_ops;
}
在dma_map_ops 中首先判断dev->archdata.dma_ops 是否为NULL,而dev->archdata.dma_ops是在do_iommu_attach 中赋值的,显然不为null。

static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
               u64 dma_base, u64 size)
{
    struct iommu_domain *domain = iommu_get_domain_for_dev(dev);

    /*
     * If the IOMMU driver has the DMA domain support that we require,
     * then the IOMMU core will have already configured a group for this
     * device, and allocated the default domain for that group.
     */
    if (!domain || iommu_dma_init_domain(domain, dma_base, size, dev)) {
        pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
            dev_name(dev));
        return false;
    }

    dev->archdata.dma_ops = &iommu_dma_ops;
    return true;
}
注意do_iommu_attach 中返回的是iommu_dma_ops。因此当用户调用dma_mmap_coherent 来申请coherent memory时,在CONFIG_IOMMU_DMA 定义了的情况下就等于在操作iommu的ops.

更多推荐

dma_mmap_coherent 如何和iommu联系在一起呢?