首页 > 学院 > 开发设计 > 正文

smmu 学习笔记之domain_alloc

2019-11-07 23:41:40
字体:
来源:转载
供稿:网友
smmu提供iommu_domain_alloc 这个接口来申请iommu_domain,举例如下:void hns_uio_set_iommu(struct nic_uio_device *PRiv, unsigned long iova,               unsigned long paddr, int gfp_order){    struct iommu_domain *domain;    int ret = 0;    domain = iommu_domain_alloc(priv->dev->bus);    if (!domain)        PRINT(KERN_ERR, "domain is null/n");}可见iommu_domain_alloc只有一个形参,这个形参是bus_typestruct iommu_domain *iommu_domain_alloc(struct bus_type *bus){    return __iommu_domain_alloc(bus, IOMMU_DOMAIN_UNMANAGED);}增加type后调用__iommu_domain_allocstatic struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,                         unsigned type){    struct iommu_domain *domain;        //判断bus和bus->iommu_ops  不能为null后    if (bus == NULL || bus->iommu_ops == NULL)        return NULL;    //调用bus->iommu_ops->domain_alloc 申请domain    domain = bus->iommu_ops->domain_alloc(type);    if (!domain)        return NULL;//给domain的ops赋值为bus->iommu_ops    domain->ops  = bus->iommu_ops;    domain->type = type;    /* Assume all sizes by default; the driver may override this later */    domain->pgsize_bitmap  = bus->iommu_ops->pgsize_bitmap;    return domain;}我们继续看bus->iommu_ops->domain_alloc。在arm_smmu_device_probe 函数中会给bus的iommu_ops 赋值#ifdef CONFIG_PCI    if (pci_bus_type.iommu_ops != &arm_smmu_ops) {        pci_request_acs();        ret = bus_set_iommu(&pci_bus_type, &arm_smmu_ops);        if (ret)            return ret;    }#endif#ifdef CONFIG_ARM_AMBA    if (amba_bustype.iommu_ops != &arm_smmu_ops) {        ret = bus_set_iommu(&amba_bustype, &arm_smmu_ops);        if (ret)            return ret;    }#endif    if (platform_bus_type.iommu_ops != &arm_smmu_ops) {        ret = bus_set_iommu(&platform_bus_type, &arm_smmu_ops);        if (ret)            return ret;    }可见总共支持三种总线。从bus_set_iommu 中就可以看到是将arm_smmu_ops 赋值给bus->iommu_opsint bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops){    int err;    if (bus->iommu_ops != NULL)        return -EBUSY;    bus->iommu_ops = ops;    /* Do IOMMU specific setup for this bus-type */    err = iommu_bus_init(bus, ops);    if (err)        bus->iommu_ops = NULL;    return err;}因此__iommu_domain_alloc 中的bus->iommu_ops->domain_alloc 就等于arm_smmu_ops->domain_alloc而arm_smmu_ops->domain_alloc = arm_smmu_domain_allocstatic struct iommu_domain *arm_smmu_domain_alloc(unsigned type){    struct arm_smmu_domain *smmu_domain;//从arm_smmu_domain_alloc 中可以看出type 只能是IOMMU_DOMAIN_UNMANAGED 和 IOMMU_DOMAIN_DMA    if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)        return NULL;    /*     * Allocate the domain and initialise some of its data structures.     * We can't really do anything meaningful until we've added a     * master.     *///调用kzalloc 来申请arm_smmu_domain结构    smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL);    if (!smmu_domain)        return NULL;//如果type == IOMMU_DOMAIN_DMA的话,还要申请cookie    if (type == IOMMU_DOMAIN_DMA &&        iommu_get_dma_cookie(&smmu_domain->domain)) {        kfree(smmu_domain);        return NULL;    }    mutex_init(&smmu_domain->init_mutex);    spin_lock_init(&smmu_domain->pgtbl_lock);    return &smmu_domain->domain;}int iommu_get_dma_cookie(struct iommu_domain *domain){    struct iommu_dma_cookie *cookie;    if (domain->iova_cookie)        return -EEXIST;    cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);    if (!cookie)        return -ENOMEM;    spin_lock_init(&cookie->msi_lock);    INIT_LIST_HEAD(&cookie->msi_page_list);    domain->iova_cookie = cookie;    return 0;}iommu_get_dma_cookie 也只是简单的申请memory和赋值而已。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表