diff options
| -rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 50cb037f3d8a..25ba546cae7f 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
| @@ -594,6 +594,8 @@ struct arm_smmu_device { | |||
| 594 | struct arm_smmu_master { | 594 | struct arm_smmu_master { |
| 595 | struct arm_smmu_device *smmu; | 595 | struct arm_smmu_device *smmu; |
| 596 | struct arm_smmu_strtab_ent ste; | 596 | struct arm_smmu_strtab_ent ste; |
| 597 | u32 *sids; | ||
| 598 | unsigned int num_sids; | ||
| 597 | }; | 599 | }; |
| 598 | 600 | ||
| 599 | /* SMMU private data for an IOMMU domain */ | 601 | /* SMMU private data for an IOMMU domain */ |
| @@ -1688,19 +1690,18 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) | |||
| 1688 | return step; | 1690 | return step; |
| 1689 | } | 1691 | } |
| 1690 | 1692 | ||
| 1691 | static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) | 1693 | static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master) |
| 1692 | { | 1694 | { |
| 1693 | int i, j; | 1695 | int i, j; |
| 1694 | struct arm_smmu_master *master = fwspec->iommu_priv; | ||
| 1695 | struct arm_smmu_device *smmu = master->smmu; | 1696 | struct arm_smmu_device *smmu = master->smmu; |
| 1696 | 1697 | ||
| 1697 | for (i = 0; i < fwspec->num_ids; ++i) { | 1698 | for (i = 0; i < master->num_sids; ++i) { |
| 1698 | u32 sid = fwspec->ids[i]; | 1699 | u32 sid = master->sids[i]; |
| 1699 | __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); | 1700 | __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); |
| 1700 | 1701 | ||
| 1701 | /* Bridged PCI devices may end up with duplicated IDs */ | 1702 | /* Bridged PCI devices may end up with duplicated IDs */ |
| 1702 | for (j = 0; j < i; j++) | 1703 | for (j = 0; j < i; j++) |
| 1703 | if (fwspec->ids[j] == sid) | 1704 | if (master->sids[j] == sid) |
| 1704 | break; | 1705 | break; |
| 1705 | if (j < i) | 1706 | if (j < i) |
| 1706 | continue; | 1707 | continue; |
| @@ -1709,13 +1710,10 @@ static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec) | |||
| 1709 | } | 1710 | } |
| 1710 | } | 1711 | } |
| 1711 | 1712 | ||
| 1712 | static void arm_smmu_detach_dev(struct device *dev) | 1713 | static void arm_smmu_detach_dev(struct arm_smmu_master *master) |
| 1713 | { | 1714 | { |
| 1714 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); | ||
| 1715 | struct arm_smmu_master *master = fwspec->iommu_priv; | ||
| 1716 | |||
| 1717 | master->ste.assigned = false; | 1715 | master->ste.assigned = false; |
| 1718 | arm_smmu_install_ste_for_dev(fwspec); | 1716 | arm_smmu_install_ste_for_dev(master); |
| 1719 | } | 1717 | } |
| 1720 | 1718 | ||
| 1721 | static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | 1719 | static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) |
| @@ -1736,7 +1734,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
| 1736 | 1734 | ||
| 1737 | /* Already attached to a different domain? */ | 1735 | /* Already attached to a different domain? */ |
| 1738 | if (ste->assigned) | 1736 | if (ste->assigned) |
| 1739 | arm_smmu_detach_dev(dev); | 1737 | arm_smmu_detach_dev(master); |
| 1740 | 1738 | ||
| 1741 | mutex_lock(&smmu_domain->init_mutex); | 1739 | mutex_lock(&smmu_domain->init_mutex); |
| 1742 | 1740 | ||
| @@ -1770,7 +1768,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
| 1770 | ste->s2_cfg = &smmu_domain->s2_cfg; | 1768 | ste->s2_cfg = &smmu_domain->s2_cfg; |
| 1771 | } | 1769 | } |
| 1772 | 1770 | ||
| 1773 | arm_smmu_install_ste_for_dev(fwspec); | 1771 | arm_smmu_install_ste_for_dev(master); |
| 1774 | out_unlock: | 1772 | out_unlock: |
| 1775 | mutex_unlock(&smmu_domain->init_mutex); | 1773 | mutex_unlock(&smmu_domain->init_mutex); |
| 1776 | return ret; | 1774 | return ret; |
| @@ -1883,12 +1881,14 @@ static int arm_smmu_add_device(struct device *dev) | |||
| 1883 | return -ENOMEM; | 1881 | return -ENOMEM; |
| 1884 | 1882 | ||
| 1885 | master->smmu = smmu; | 1883 | master->smmu = smmu; |
| 1884 | master->sids = fwspec->ids; | ||
| 1885 | master->num_sids = fwspec->num_ids; | ||
| 1886 | fwspec->iommu_priv = master; | 1886 | fwspec->iommu_priv = master; |
| 1887 | } | 1887 | } |
| 1888 | 1888 | ||
| 1889 | /* Check the SIDs are in range of the SMMU and our stream table */ | 1889 | /* Check the SIDs are in range of the SMMU and our stream table */ |
| 1890 | for (i = 0; i < fwspec->num_ids; i++) { | 1890 | for (i = 0; i < master->num_sids; i++) { |
| 1891 | u32 sid = fwspec->ids[i]; | 1891 | u32 sid = master->sids[i]; |
| 1892 | 1892 | ||
| 1893 | if (!arm_smmu_sid_in_range(smmu, sid)) | 1893 | if (!arm_smmu_sid_in_range(smmu, sid)) |
| 1894 | return -ERANGE; | 1894 | return -ERANGE; |
| @@ -1922,7 +1922,7 @@ static void arm_smmu_remove_device(struct device *dev) | |||
| 1922 | master = fwspec->iommu_priv; | 1922 | master = fwspec->iommu_priv; |
| 1923 | smmu = master->smmu; | 1923 | smmu = master->smmu; |
| 1924 | if (master && master->ste.assigned) | 1924 | if (master && master->ste.assigned) |
| 1925 | arm_smmu_detach_dev(dev); | 1925 | arm_smmu_detach_dev(master); |
| 1926 | iommu_group_remove_device(dev); | 1926 | iommu_group_remove_device(dev); |
| 1927 | iommu_device_unlink(&smmu->iommu, dev); | 1927 | iommu_device_unlink(&smmu->iommu, dev); |
| 1928 | kfree(master); | 1928 | kfree(master); |
