mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/smmu: Add remove_device callback for smmu_iommu ops
Add remove_device callback for removing the device entry from smmu-master using following steps: 1. Find if SMMU master exists for the device node. 2. Check if device is currently in use. 3. Remove the SMMU master. Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com> Reviewed-by: Luca Fancellu <luca.fancellu@arm.com> Acked-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
de89833857
commit
3b27fff436
1 file changed
+60
@@ -815,6 +815,19 @@ static int insert_smmu_master(struct arm_smmu_device *smmu,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int remove_smmu_master(struct arm_smmu_device *smmu,
|
||||
struct arm_smmu_master *master)
|
||||
{
|
||||
if (!smmu->masters.rb_node) {
|
||||
ASSERT_UNREACHABLE();
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rb_erase(&master->node, &smmu->masters);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arm_smmu_dt_add_device_legacy(struct arm_smmu_device *smmu,
|
||||
struct device *dev,
|
||||
struct iommu_fwspec *fwspec)
|
||||
@@ -852,6 +865,32 @@ static int arm_smmu_dt_add_device_legacy(struct arm_smmu_device *smmu,
|
||||
return insert_smmu_master(smmu, master);
|
||||
}
|
||||
|
||||
static int arm_smmu_dt_remove_device_legacy(struct arm_smmu_device *smmu,
|
||||
struct device *dev)
|
||||
{
|
||||
struct arm_smmu_master *master;
|
||||
struct device_node *dev_node = dev_get_dev_node(dev);
|
||||
int ret;
|
||||
|
||||
master = find_smmu_master(smmu, dev_node);
|
||||
if (master == NULL) {
|
||||
dev_err(dev,
|
||||
"No registrations found for master device %s\n",
|
||||
dev_node->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = remove_smmu_master(smmu, master);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Protected by dt_host_lock and dtdevs_lock as caller holds these locks. */
|
||||
dev_node->is_protected = false;
|
||||
|
||||
kfree(master);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int register_smmu_master(struct arm_smmu_device *smmu,
|
||||
struct device *dev,
|
||||
struct of_phandle_args *masterspec)
|
||||
@@ -875,6 +914,26 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
|
||||
fwspec);
|
||||
}
|
||||
|
||||
/*
|
||||
* The driver which supports generic IOMMU DT bindings must have this
|
||||
* callback implemented.
|
||||
*/
|
||||
static int arm_smmu_dt_remove_device_generic(u8 devfn, struct device *dev)
|
||||
{
|
||||
struct arm_smmu_device *smmu;
|
||||
struct iommu_fwspec *fwspec;
|
||||
|
||||
fwspec = dev_iommu_fwspec_get(dev);
|
||||
if (fwspec == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
smmu = find_smmu(fwspec->iommu_dev);
|
||||
if (smmu == NULL)
|
||||
return -ENXIO;
|
||||
|
||||
return arm_smmu_dt_remove_device_legacy(smmu, dev);
|
||||
}
|
||||
|
||||
static int arm_smmu_dt_add_device_generic(u8 devfn, struct device *dev)
|
||||
{
|
||||
struct arm_smmu_device *smmu;
|
||||
@@ -2859,6 +2918,7 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
|
||||
.init = arm_smmu_iommu_domain_init,
|
||||
.hwdom_init = arch_iommu_hwdom_init,
|
||||
.add_device = arm_smmu_dt_add_device_generic,
|
||||
.remove_device = arm_smmu_dt_remove_device_generic,
|
||||
.teardown = arm_smmu_iommu_domain_teardown,
|
||||
.iotlb_flush = arm_smmu_iotlb_flush,
|
||||
.assign_device = arm_smmu_assign_dev,
|
||||
|
||||