smmu学习笔记之iommu_fwspec

本文解析了ARM SMMU初始化过程,详细介绍了arm_smmu_iort_xlate函数如何初始化dev->iommu_fwspec,并通过实例展示了如何通过iommu_fwspec获取arm_smmu_device。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在arm_smmu_iort_xlate 主要用于初始化dev->iommu_fwspec 这个结构体
static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
      struct fwnode_handle *fwnode,
      const struct iommu_ops *ops)
{
int ret = iommu_fwspec_init(dev, fwnode, ops);


if (!ret)
ret = iommu_fwspec_add_ids(dev, &streamid, 1);


return ret;
}
首先调用iommu_fwspec_init 来为dev->iommu_fwspec 申请空间
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
     const struct iommu_ops *ops)
{
struct iommu_fwspec *fwspec = dev->iommu_fwspec;


if (fwspec)
return ops == fwspec->ops ? 0 : -EINVAL;


fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL);
if (!fwspec)
return -ENOMEM;


of_node_get(to_of_node(iommu_fwnode));
//给fwspec 赋值
fwspec->iommu_fwnode = iommu_fwnode;
fwspec->ops = ops;
//保存到dev->iommu_fwspec 中
dev->iommu_fwspec = fwspec;
return 0;
}
这个函数的第三个参数,针对arm来讲的话,就是arm_smmu_ops。
第一次申请的时候fwspec肯定是NULL,因此调用kzalloc 申请空间并清零.由于我们是ACPI 模式,因此of_node_get(to_of_node(iommu_fwnode));都是空函数
这里给fwspec 赋值后,再保存到dev->iommu_fwspec 中。
回到arm_smmu_iort_xlate 中调用iommu_fwspec_init 成功申请iommu_fwspec空间然后赋值,最后保存到dev->iommu_fwspec 中之后,就调用iommu_fwspec_add_ids
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
{
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
size_t size;
int i;


if (!fwspec)
return -EINVAL;


size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + num_ids]);
if (size > sizeof(*fwspec)) {
fwspec = krealloc(dev->iommu_fwspec, size, GFP_KERNEL);
if (!fwspec)
return -ENOMEM;
}


for (i = 0; i < num_ids; i++)
fwspec->ids[fwspec->num_ids + i] = ids[i];


fwspec->num_ids += num_ids;
dev->iommu_fwspec = fwspec;
return 0;
}
从arm_smmu_iort_xlate 中可以知道iommu_fwspec_add_ids的第二个参数ids代表的是streamid,第三个参数num_ids 等于1
在iommu_fwspec_add_ids 中将streamid添加到fwspec->ids 这个数组中,饭后更新整个dev中包含的streamid的个数,然后重新更新dev->iommu_fwspec。


在code中对iommu_fwspec的使用除了获取streadid外,还会通过iommu_fwspec->iommu_priv 得到 arm_smmu_device
用法如下:


struct arm_smmu_device *smmu;
struct arm_smmu_master_data *master;
struct arm_smmu_strtab_ent *ste;


if (!dev->iommu_fwspec)
return -ENOENT;


master = dev->iommu_fwspec->iommu_priv;
smmu = master->smmu;
ste = &master->ste;


这样就可以通过iommu_fwspec 得到arm_smmu_master_data,再从arm_smmu_master_data 中得到arm_smmu_device和arm_smmu_strtab_ent
总结一下,dev->iommu_fwspec 保存这个dev和smmu相关的信息.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值