smmu学习笔记之fwnode_handle代表smmu iort port在内存中的存在其作用是找到iommu_ops

在iort_init_platform_devices 中会从iort_table 中找node type是ACPI_IORT_NODE_SMMU 或者ACPI_IORT_NODE_SMMU_V3 的node,如果找到就申请一个fwnode_handle 类型的空间
struct fwnode_handle *fwnode;
fwnode = acpi_alloc_fwnode_static();
iort_set_fwnode(iort_node, fwnode);

static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
{
    struct fwnode_handle *fwnode;

    fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
    if (!fwnode)
        return NULL;

    fwnode->type = FWNODE_ACPI_STATIC;

    return fwnode;
}
从acpi_alloc_fwnode_static 可以看出首先申请一个fwnode_handle *fwnode,然后给type赋值FWNODE_ACPI_STATIC

而fwnode_type 总共有下面这几种.
enum fwnode_type {
    FWNODE_INVALID = 0,
    FWNODE_OF,
    FWNODE_ACPI,
    FWNODE_ACPI_DATA,
    FWNODE_ACPI_STATIC,
    FWNODE_PDATA,
    FWNODE_IRQCHIP
};

申请到fwnode_handle *fwnode 后再通过iort_set_fwnode 将fwnode 添加到iort_fwnode_list 中
static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
                  struct fwnode_handle *fwnode)
{
    struct iort_fwnode *np;

    np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);

    if (WARN_ON(!np))
        return -ENOMEM;

    INIT_LIST_HEAD(&np->list);
    np->iort_node = iort_node;
    np->fwnode = fwnode;

    spin_lock(&iort_fwnode_lock);
    list_add_tail(&np->list, &iort_fwnode_list);
    spin_unlock(&iort_fwnode_lock);

    return 0;
}
在iort_set_fwnode 中先申请一个iort_fwnode *np,然后分别给iort_node和fwnode 赋值,然后添加到iort_fwnode_list 中,后面就可以通过
static inline
struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
{
    struct iort_fwnode *curr;
    struct fwnode_handle *fwnode = NULL;

    spin_lock(&iort_fwnode_lock);
    list_for_each_entry(curr, &iort_fwnode_list, list) {
        if (curr->iort_node == node) {
            fwnode = curr->fwnode;
            break;
        }
    }
    spin_unlock(&iort_fwnode_lock);

    return fwnode;
}
来得到fwnode。总的来说fwnode_handle代表smmu 的firmware device node ,得到fwnode 后最终在iort_add_smmu_platform_device赋值给    pdev->dev.fwnode = fwnode; 总的感觉fwnode最大的作用还是用于匹配node。例如下面的code中欧给你就通过对比fwnode来的到iommu_ops

const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
{
    struct iommu_fwentry *node;
    const struct iommu_ops *ops = NULL;

    spin_lock(&iommu_fwentry_lock);
    list_for_each_entry(node, &iommu_fwentry_list, list)
        if (node->fwnode == fwnode) {
            ops = node->ops;
            break;
        }
    spin_unlock(&iommu_fwentry_lock);
    return ops;
}
例如在fwnode_iommu_get_ops 中就是通过iommu_fwentry *node 是否等于fwnode_handle *fwnode 来得到device的iommu_ops。
与之对应的是
void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
              const struct iommu_ops *ops)
{
    struct iommu_fwentry *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);

    if (WARN_ON(!iommu))
        return;

    if (is_of_node(fwnode))
        of_node_get(to_of_node(fwnode));

    INIT_LIST_HEAD(&iommu->list);
    iommu->fwnode = fwnode;
    iommu->ops = ops;
    spin_lock(&iommu_fwentry_lock);
    list_add_tail(&iommu->list, &iommu_fwentry_list);
    spin_unlock(&iommu_fwentry_lock);
}
明显看到在iommu_fwentry *iommu 中将fwnode和ops绑定,后面就可以通过fwnode_iommu_get_ops 来查找iommu_fwentry_list 来得到iommu_ops
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值