Skip to content

Commit

Permalink
iommu/arm-smmu-v3: Return -EBUSY when trying to re-add a device
Browse files Browse the repository at this point in the history
Although we WARN in arm_smmu_add_device() if the device being added has
been added already without a subsequent call to arm_smmu_remove_device(),
we still continue half-heartedly, initialising the stream-table for any
new StreamIDs that may have magically appeared and re-establishing device
links that should still be there from last time.

Given that calling ->add_device() twice without removing the device in the
meantime is indicative of an error in the caller, just return -EBUSY after
warning.

Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Jean Philippe-Brucker <jean-philippe@linaro.org>
Signed-off-by: Will Deacon <will@kernel.org>
  • Loading branch information
Will Deacon committed Jan 15, 2020

Unverified

No user is associated with the committer email.
1 parent a2be621 commit 92c1d36
Showing 1 changed file with 16 additions and 21 deletions.
37 changes: 16 additions & 21 deletions drivers/iommu/arm-smmu-v3.c
Original file line number Diff line number Diff line change
@@ -2794,28 +2794,23 @@ static int arm_smmu_add_device(struct device *dev)

if (!fwspec || fwspec->ops != &arm_smmu_ops)
return -ENODEV;
/*
* We _can_ actually withstand dodgy bus code re-calling add_device()
* without an intervening remove_device()/of_xlate() sequence, but
* we're not going to do so quietly...
*/
if (WARN_ON_ONCE(fwspec->iommu_priv)) {
master = fwspec->iommu_priv;
smmu = master->smmu;
} else {
smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
if (!smmu)
return -ENODEV;
master = kzalloc(sizeof(*master), GFP_KERNEL);
if (!master)
return -ENOMEM;

master->dev = dev;
master->smmu = smmu;
master->sids = fwspec->ids;
master->num_sids = fwspec->num_ids;
fwspec->iommu_priv = master;
}
if (WARN_ON_ONCE(fwspec->iommu_priv))
return -EBUSY;

smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
if (!smmu)
return -ENODEV;

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

master->dev = dev;
master->smmu = smmu;
master->sids = fwspec->ids;
master->num_sids = fwspec->num_ids;
fwspec->iommu_priv = master;

/* Check the SIDs are in range of the SMMU and our stream table */
for (i = 0; i < master->num_sids; i++) {

0 comments on commit 92c1d36

Please sign in to comment.