Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 43 additions & 17 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3935,6 +3935,20 @@ int arm_smmu_cmdq_init(struct arm_smmu_device *smmu,
return 0;
}

static void arm_smmu_free_iopf_action(void *data)
{
struct iopf_queue *queue = data;

iopf_queue_free(queue);
}

static void arm_smmu_destroy_vmid_map(void *data)
{
struct ida *ida = data;

ida_destroy(ida);
}

static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
{
int ret;
Expand Down Expand Up @@ -3962,6 +3976,11 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
smmu->evtq.iopf = iopf_queue_alloc(dev_name(smmu->dev));
if (!smmu->evtq.iopf)
return -ENOMEM;
ret = devm_add_action_or_reset(smmu->dev,
arm_smmu_free_iopf_action,
smmu->evtq.iopf);
if (ret)
return ret;
}

/* priq */
Expand Down Expand Up @@ -4235,7 +4254,8 @@ static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
out:
ida_init(&smmu->vmid_map);

return 0;
return devm_add_action_or_reset(smmu->dev, arm_smmu_destroy_vmid_map,
&smmu->vmid_map);
}

static int arm_smmu_init_structures(struct arm_smmu_device *smmu)
Expand Down Expand Up @@ -4464,6 +4484,15 @@ static int arm_smmu_device_disable(struct arm_smmu_device *smmu)
return ret;
}

static void arm_smmu_disable_action(void *data)
{
struct arm_smmu_device *smmu = data;

if (smmu->impl_ops && smmu->impl_ops->device_disable)
smmu->impl_ops->device_disable(smmu);
arm_smmu_device_disable(smmu);
}

static void arm_smmu_write_strtab(struct arm_smmu_device *smmu)
{
struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
Expand Down Expand Up @@ -5300,7 +5329,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
/* Initialise in-memory data structures */
ret = arm_smmu_init_structures(smmu);
if (ret)
goto err_free_iopf;
return ret;

/* Record our private device structure */
platform_set_drvdata(pdev, smmu);
Expand All @@ -5310,30 +5339,30 @@ static int arm_smmu_device_probe(struct platform_device *pdev)

/* Reset the device */
ret = arm_smmu_device_reset(smmu);
if (ret) {
arm_smmu_device_disable(smmu);
return ret;
}

/* Register last so it unwinds first, while the CMDQ is still up. */
ret = devm_add_action_or_reset(smmu->dev, arm_smmu_disable_action, smmu);
if (ret)
goto err_disable;
return ret;

/* And we're up. Go go go! */
ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
"smmu3.%pa", &ioaddr);
if (ret)
goto err_disable;
return ret;

ret = iommu_device_register(&smmu->iommu, &arm_smmu_ops, dev);
if (ret) {
dev_err(dev, "Failed to register iommu\n");
goto err_free_sysfs;
iommu_device_sysfs_remove(&smmu->iommu);
return ret;
}

return 0;

err_free_sysfs:
iommu_device_sysfs_remove(&smmu->iommu);
err_disable:
arm_smmu_device_disable(smmu);
err_free_iopf:
iopf_queue_free(smmu->evtq.iopf);
return ret;
}

static void arm_smmu_device_remove(struct platform_device *pdev)
Expand All @@ -5342,16 +5371,13 @@ static void arm_smmu_device_remove(struct platform_device *pdev)

iommu_device_unregister(&smmu->iommu);
iommu_device_sysfs_remove(&smmu->iommu);
arm_smmu_device_disable(smmu);
iopf_queue_free(smmu->evtq.iopf);
ida_destroy(&smmu->vmid_map);
}

static void arm_smmu_device_shutdown(struct platform_device *pdev)
{
struct arm_smmu_device *smmu = platform_get_drvdata(pdev);

arm_smmu_device_disable(smmu);
arm_smmu_disable_action(smmu);
}

static const struct of_device_id arm_smmu_of_match[] = {
Expand Down
1 change: 1 addition & 0 deletions drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ struct arm_smmu_strtab_cfg {

struct arm_smmu_impl_ops {
int (*device_reset)(struct arm_smmu_device *smmu);
void (*device_disable)(struct arm_smmu_device *smmu);
void (*device_remove)(struct arm_smmu_device *smmu);
int (*init_structures)(struct arm_smmu_device *smmu);
struct arm_smmu_cmdq *(*get_secondary_cmdq)(
Expand Down
15 changes: 13 additions & 2 deletions drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,6 @@ static void tegra241_cmdqv_remove_vintf(struct tegra241_cmdqv *cmdqv, u16 idx)
struct tegra241_vintf *vintf = cmdqv->vintfs[idx];
u16 lidx;

tegra241_vintf_hw_deinit(vintf);

/* Remove LVCMDQ resources */
for (lidx = 0; lidx < vintf->cmdqv->num_lvcmdqs_per_vintf; lidx++)
if (vintf->lvcmdqs[lidx])
Expand All @@ -779,6 +777,17 @@ static void tegra241_cmdqv_remove_vintf(struct tegra241_cmdqv *cmdqv, u16 idx)
}
}

static void tegra241_cmdqv_hw_disable(struct arm_smmu_device *smmu)
{
struct tegra241_cmdqv *cmdqv =
container_of(smmu, struct tegra241_cmdqv, smmu);
u16 idx;

for (idx = 0; idx < cmdqv->num_vintfs; idx++)
if (cmdqv->vintfs[idx])
tegra241_vintf_hw_deinit(cmdqv->vintfs[idx]);
}

static void tegra241_cmdqv_remove(struct arm_smmu_device *smmu)
{
struct tegra241_cmdqv *cmdqv =
Expand Down Expand Up @@ -844,6 +853,7 @@ static struct arm_smmu_impl_ops tegra241_cmdqv_impl_ops = {
/* For in-kernel use */
.get_secondary_cmdq = tegra241_cmdqv_get_cmdq,
.device_reset = tegra241_cmdqv_hw_reset,
.device_disable = tegra241_cmdqv_hw_disable,
.device_remove = tegra241_cmdqv_remove,
/* For user-space use */
.hw_info = tegra241_cmdqv_hw_info,
Expand Down Expand Up @@ -1152,6 +1162,7 @@ static void tegra241_cmdqv_destroy_vintf_user(struct iommufd_viommu *viommu)
if (vintf->mmap_offset)
iommufd_viommu_destroy_mmap(&vintf->vsmmu.core,
vintf->mmap_offset);
tegra241_vintf_hw_deinit(vintf);
tegra241_cmdqv_remove_vintf(vintf->cmdqv, vintf->idx);
}

Expand Down
Loading