aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorPeng Fan <van.freenix@gmail.com>2015-11-20 03:56:18 -0500
committerWill Deacon <will.deacon@arm.com>2015-12-17 07:05:33 -0500
commit9a4a9d8c34bc0b0102e8a9dd67ee3910b0bfaeb4 (patch)
treed3f00b4266cfbe5cc38473296e206c07d5e91159 /drivers/iommu
parenta0eacd89e35e55aad284cc2e6865bf2dcf7037ba (diff)
iommu/arm-smmu: Correct group reference count
The basic flow for add a device: arm_smmu_add_device |->iommu_group_get_for_dev |->iommu_group_get return group; (1) |->ops->device_group : Init/increase reference count to/by 1. |->iommu_group_add_device : Increase reference count by 1. return group (2) |->return 0; Since we are adding one device, the flow is (2) and the group reference count will be increased by 2. So, we need to add iommu_group_put at the end of arm_smmu_add_device to decrease the count by 1. Also take the failure path into consideration when fail to add a device. Signed-off-by: Peng Fan <van.freenix@gmail.com> Cc: Will Deacon <will.deacon@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/arm-smmu-v3.c18
-rw-r--r--drivers/iommu/arm-smmu.c1
2 files changed, 12 insertions, 7 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 2e3e235f509c..3ea4d576bf08 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1809,13 +1809,13 @@ static int arm_smmu_add_device(struct device *dev)
1809 smmu = arm_smmu_get_for_pci_dev(pdev); 1809 smmu = arm_smmu_get_for_pci_dev(pdev);
1810 if (!smmu) { 1810 if (!smmu) {
1811 ret = -ENOENT; 1811 ret = -ENOENT;
1812 goto out_put_group; 1812 goto out_remove_dev;
1813 } 1813 }
1814 1814
1815 smmu_group = kzalloc(sizeof(*smmu_group), GFP_KERNEL); 1815 smmu_group = kzalloc(sizeof(*smmu_group), GFP_KERNEL);
1816 if (!smmu_group) { 1816 if (!smmu_group) {
1817 ret = -ENOMEM; 1817 ret = -ENOMEM;
1818 goto out_put_group; 1818 goto out_remove_dev;
1819 } 1819 }
1820 1820
1821 smmu_group->ste.valid = true; 1821 smmu_group->ste.valid = true;
@@ -1831,20 +1831,20 @@ static int arm_smmu_add_device(struct device *dev)
1831 for (i = 0; i < smmu_group->num_sids; ++i) { 1831 for (i = 0; i < smmu_group->num_sids; ++i) {
1832 /* If we already know about this SID, then we're done */ 1832 /* If we already know about this SID, then we're done */
1833 if (smmu_group->sids[i] == sid) 1833 if (smmu_group->sids[i] == sid)
1834 return 0; 1834 goto out_put_group;
1835 } 1835 }
1836 1836
1837 /* Check the SID is in range of the SMMU and our stream table */ 1837 /* Check the SID is in range of the SMMU and our stream table */
1838 if (!arm_smmu_sid_in_range(smmu, sid)) { 1838 if (!arm_smmu_sid_in_range(smmu, sid)) {
1839 ret = -ERANGE; 1839 ret = -ERANGE;
1840 goto out_put_group; 1840 goto out_remove_dev;
1841 } 1841 }
1842 1842
1843 /* Ensure l2 strtab is initialised */ 1843 /* Ensure l2 strtab is initialised */
1844 if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) { 1844 if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
1845 ret = arm_smmu_init_l2_strtab(smmu, sid); 1845 ret = arm_smmu_init_l2_strtab(smmu, sid);
1846 if (ret) 1846 if (ret)
1847 goto out_put_group; 1847 goto out_remove_dev;
1848 } 1848 }
1849 1849
1850 /* Resize the SID array for the group */ 1850 /* Resize the SID array for the group */
@@ -1854,16 +1854,20 @@ static int arm_smmu_add_device(struct device *dev)
1854 if (!sids) { 1854 if (!sids) {
1855 smmu_group->num_sids--; 1855 smmu_group->num_sids--;
1856 ret = -ENOMEM; 1856 ret = -ENOMEM;
1857 goto out_put_group; 1857 goto out_remove_dev;
1858 } 1858 }
1859 1859
1860 /* Add the new SID */ 1860 /* Add the new SID */
1861 sids[smmu_group->num_sids - 1] = sid; 1861 sids[smmu_group->num_sids - 1] = sid;
1862 smmu_group->sids = sids; 1862 smmu_group->sids = sids;
1863 return 0;
1864 1863
1865out_put_group: 1864out_put_group:
1866 iommu_group_put(group); 1865 iommu_group_put(group);
1866 return 0;
1867
1868out_remove_dev:
1869 iommu_group_remove_device(dev);
1870 iommu_group_put(group);
1867 return ret; 1871 return ret;
1868} 1872}
1869 1873
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1ce4b85d5216..6ed169bcb39d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1355,6 +1355,7 @@ static int arm_smmu_add_device(struct device *dev)
1355 if (IS_ERR(group)) 1355 if (IS_ERR(group))
1356 return PTR_ERR(group); 1356 return PTR_ERR(group);
1357 1357
1358 iommu_group_put(group);
1358 return 0; 1359 return 0;
1359} 1360}
1360 1361