diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-01 17:44:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-01 17:44:22 -0400 |
commit | 44b061f77f70e21031444e3611dfddbb80b4defc (patch) | |
tree | 9bb5bb46f8015c856fdf2957a9d0d260f0f19e15 | |
parent | f822dcc63f966fc79b11a8254fa0942b1aa8c71e (diff) | |
parent | 7a5a566eab48da7522f601f96aef3af102178046 (diff) |
Merge tag 'iommu-fixes-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pul IOMMU fixes from Joerg Roedel:
"Four fixes have queued up to fix regressions introduced after v4.1:
- Don't fail IOMMU driver initialization when the add_device
call-back returns -ENODEV, as that just means that the device is
not translated by the IOMMU. This is pretty common on ARM.
- Two fixes for the ARM-SMMU driver for a wrong feature check and to
remove a redundant NULL check.
- A fix for the AMD IOMMU driver to fix a boot panic on systems where
the BIOS requests Unity Mappings in the IVRS table"
* tag 'iommu-fixes-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
iommu/amd: Introduce protection_domain_init() function
iommu/arm-smmu: Delete an unnecessary check before the function call "free_io_pgtable_ops"
iommu/arm-smmu: Fix broken ATOS check
iommu: Ignore -ENODEV errors from add_device call-back
-rw-r--r-- | drivers/iommu/amd_iommu.c | 26 | ||||
-rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 3 | ||||
-rw-r--r-- | drivers/iommu/arm-smmu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/iommu.c | 13 |
4 files changed, 30 insertions, 14 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index d3e5e9abe3b6..a57e9b749895 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -117,6 +117,7 @@ struct kmem_cache *amd_iommu_irq_cache; | |||
117 | 117 | ||
118 | static void update_domain(struct protection_domain *domain); | 118 | static void update_domain(struct protection_domain *domain); |
119 | static int alloc_passthrough_domain(void); | 119 | static int alloc_passthrough_domain(void); |
120 | static int protection_domain_init(struct protection_domain *domain); | ||
120 | 121 | ||
121 | /**************************************************************************** | 122 | /**************************************************************************** |
122 | * | 123 | * |
@@ -1881,12 +1882,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void) | |||
1881 | if (!dma_dom) | 1882 | if (!dma_dom) |
1882 | return NULL; | 1883 | return NULL; |
1883 | 1884 | ||
1884 | spin_lock_init(&dma_dom->domain.lock); | 1885 | if (protection_domain_init(&dma_dom->domain)) |
1885 | |||
1886 | dma_dom->domain.id = domain_id_alloc(); | ||
1887 | if (dma_dom->domain.id == 0) | ||
1888 | goto free_dma_dom; | 1886 | goto free_dma_dom; |
1889 | INIT_LIST_HEAD(&dma_dom->domain.dev_list); | 1887 | |
1890 | dma_dom->domain.mode = PAGE_MODE_2_LEVEL; | 1888 | dma_dom->domain.mode = PAGE_MODE_2_LEVEL; |
1891 | dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL); | 1889 | dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL); |
1892 | dma_dom->domain.flags = PD_DMA_OPS_MASK; | 1890 | dma_dom->domain.flags = PD_DMA_OPS_MASK; |
@@ -2916,6 +2914,18 @@ static void protection_domain_free(struct protection_domain *domain) | |||
2916 | kfree(domain); | 2914 | kfree(domain); |
2917 | } | 2915 | } |
2918 | 2916 | ||
2917 | static int protection_domain_init(struct protection_domain *domain) | ||
2918 | { | ||
2919 | spin_lock_init(&domain->lock); | ||
2920 | mutex_init(&domain->api_lock); | ||
2921 | domain->id = domain_id_alloc(); | ||
2922 | if (!domain->id) | ||
2923 | return -ENOMEM; | ||
2924 | INIT_LIST_HEAD(&domain->dev_list); | ||
2925 | |||
2926 | return 0; | ||
2927 | } | ||
2928 | |||
2919 | static struct protection_domain *protection_domain_alloc(void) | 2929 | static struct protection_domain *protection_domain_alloc(void) |
2920 | { | 2930 | { |
2921 | struct protection_domain *domain; | 2931 | struct protection_domain *domain; |
@@ -2924,12 +2934,8 @@ static struct protection_domain *protection_domain_alloc(void) | |||
2924 | if (!domain) | 2934 | if (!domain) |
2925 | return NULL; | 2935 | return NULL; |
2926 | 2936 | ||
2927 | spin_lock_init(&domain->lock); | 2937 | if (protection_domain_init(domain)) |
2928 | mutex_init(&domain->api_lock); | ||
2929 | domain->id = domain_id_alloc(); | ||
2930 | if (!domain->id) | ||
2931 | goto out_err; | 2938 | goto out_err; |
2932 | INIT_LIST_HEAD(&domain->dev_list); | ||
2933 | 2939 | ||
2934 | add_domain_to_list(domain); | 2940 | add_domain_to_list(domain); |
2935 | 2941 | ||
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index f14130121298..8e9ec81ce4bb 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
@@ -1389,8 +1389,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) | |||
1389 | struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); | 1389 | struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); |
1390 | struct arm_smmu_device *smmu = smmu_domain->smmu; | 1390 | struct arm_smmu_device *smmu = smmu_domain->smmu; |
1391 | 1391 | ||
1392 | if (smmu_domain->pgtbl_ops) | 1392 | free_io_pgtable_ops(smmu_domain->pgtbl_ops); |
1393 | free_io_pgtable_ops(smmu_domain->pgtbl_ops); | ||
1394 | 1393 | ||
1395 | /* Free the CD and ASID, if we allocated them */ | 1394 | /* Free the CD and ASID, if we allocated them */ |
1396 | if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { | 1395 | if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { |
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index dce041b1c139..4cd0c29cb585 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -1566,7 +1566,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1566 | return -ENODEV; | 1566 | return -ENODEV; |
1567 | } | 1567 | } |
1568 | 1568 | ||
1569 | if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) { | 1569 | if ((id & ID0_S1TS) && ((smmu->version == 1) || !(id & ID0_ATOSNS))) { |
1570 | smmu->features |= ARM_SMMU_FEAT_TRANS_OPS; | 1570 | smmu->features |= ARM_SMMU_FEAT_TRANS_OPS; |
1571 | dev_notice(smmu->dev, "\taddress translation ops\n"); | 1571 | dev_notice(smmu->dev, "\taddress translation ops\n"); |
1572 | } | 1572 | } |
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 49e7542510d1..f286090931cc 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -847,13 +847,24 @@ static int add_iommu_group(struct device *dev, void *data) | |||
847 | { | 847 | { |
848 | struct iommu_callback_data *cb = data; | 848 | struct iommu_callback_data *cb = data; |
849 | const struct iommu_ops *ops = cb->ops; | 849 | const struct iommu_ops *ops = cb->ops; |
850 | int ret; | ||
850 | 851 | ||
851 | if (!ops->add_device) | 852 | if (!ops->add_device) |
852 | return 0; | 853 | return 0; |
853 | 854 | ||
854 | WARN_ON(dev->iommu_group); | 855 | WARN_ON(dev->iommu_group); |
855 | 856 | ||
856 | return ops->add_device(dev); | 857 | ret = ops->add_device(dev); |
858 | |||
859 | /* | ||
860 | * We ignore -ENODEV errors for now, as they just mean that the | ||
861 | * device is not translated by an IOMMU. We still care about | ||
862 | * other errors and fail to initialize when they happen. | ||
863 | */ | ||
864 | if (ret == -ENODEV) | ||
865 | ret = 0; | ||
866 | |||
867 | return ret; | ||
857 | } | 868 | } |
858 | 869 | ||
859 | static int remove_iommu_group(struct device *dev, void *data) | 870 | static int remove_iommu_group(struct device *dev, void *data) |