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:
Vikram Garhwal authored and Stefano Stabellini committed 2023-09-05 18:33:42 -07:00
1 parent de89833857
commit 3b27fff436
1 file changed
+60
+60
View File
@@ -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,
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.