diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-11-27 10:41:19 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-11-27 10:41:19 -0800 |
commit | 6adf33a5e42feada39d52eebd389d2019202e993 (patch) | |
tree | d58dc66a60e9da89a4332938e7f6362fd6a6a797 /drivers/iommu | |
parent | 43d6ecd97c0c69acffc918cc18cdabdfcaa55354 (diff) | |
parent | d76b42e92780c3587c1a998a3a943b501c137553 (diff) | |
download | linux-stable-6adf33a5e42feada39d52eebd389d2019202e993.tar.gz linux-stable-6adf33a5e42feada39d52eebd389d2019202e993.tar.bz2 linux-stable-6adf33a5e42feada39d52eebd389d2019202e993.zip |
Merge tag 'iommu-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull iommu fixes from Will Deacon:
"Here's another round of IOMMU fixes for -rc6 consisting mainly of a
bunch of independent driver fixes. Thomas agreed for me to take the
x86 'tboot' fix here, as it fixes a regression introduced by a vt-d
change.
- Fix intel iommu driver when running on devices without VCCAP_REG
- Fix swiotlb and "iommu=pt" interaction under TXT (tboot)
- Fix missing return value check during device probe()
- Fix probe ordering for Qualcomm SMMU implementation
- Ensure page-sized mappings are used for AMD IOMMU buffers with SNP
RMP"
* tag 'iommu-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
iommu/vt-d: Don't read VCCAP register unless it exists
x86/tboot: Don't disable swiotlb when iommu is forced on
iommu: Check return of __iommu_attach_device()
arm-smmu-qcom: Ensure the qcom_scm driver has finished probing
iommu/amd: Enforce 4k mapping for certain IOMMU data structures
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd/init.c | 27 | ||||
-rw-r--r-- | drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 4 | ||||
-rw-r--r-- | drivers/iommu/intel/dmar.c | 3 | ||||
-rw-r--r-- | drivers/iommu/intel/iommu.c | 4 | ||||
-rw-r--r-- | drivers/iommu/iommu.c | 10 |
5 files changed, 36 insertions, 12 deletions
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 82e4af8f09bb..23a790f8f550 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -29,6 +29,7 @@ #include <asm/iommu_table.h> #include <asm/io_apic.h> #include <asm/irq_remapping.h> +#include <asm/set_memory.h> #include <linux/crash_dump.h> @@ -672,11 +673,27 @@ static void __init free_command_buffer(struct amd_iommu *iommu) free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); } +static void *__init iommu_alloc_4k_pages(struct amd_iommu *iommu, + gfp_t gfp, size_t size) +{ + int order = get_order(size); + void *buf = (void *)__get_free_pages(gfp, order); + + if (buf && + iommu_feature(iommu, FEATURE_SNP) && + set_memory_4k((unsigned long)buf, (1 << order))) { + free_pages((unsigned long)buf, order); + buf = NULL; + } + + return buf; +} + /* allocates the memory where the IOMMU will log its events to */ static int __init alloc_event_buffer(struct amd_iommu *iommu) { - iommu->evt_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - get_order(EVT_BUFFER_SIZE)); + iommu->evt_buf = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, + EVT_BUFFER_SIZE); return iommu->evt_buf ? 0 : -ENOMEM; } @@ -715,8 +732,8 @@ static void __init free_event_buffer(struct amd_iommu *iommu) /* allocates the memory where the IOMMU will log its events to */ static int __init alloc_ppr_log(struct amd_iommu *iommu) { - iommu->ppr_log = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, - get_order(PPR_LOG_SIZE)); + iommu->ppr_log = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, + PPR_LOG_SIZE); return iommu->ppr_log ? 0 : -ENOMEM; } @@ -838,7 +855,7 @@ static int iommu_init_ga(struct amd_iommu *iommu) static int __init alloc_cwwb_sem(struct amd_iommu *iommu) { - iommu->cmd_sem = (void *)get_zeroed_page(GFP_KERNEL); + iommu->cmd_sem = iommu_alloc_4k_pages(iommu, GFP_KERNEL | __GFP_ZERO, 1); return iommu->cmd_sem ? 0 : -ENOMEM; } diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index be4318044f96..702fbaa6c9ad 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -69,6 +69,10 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu) { struct qcom_smmu *qsmmu; + /* Check to make sure qcom_scm has finished probing */ + if (!qcom_scm_is_available()) + return ERR_PTR(-EPROBE_DEFER); + qsmmu = devm_kzalloc(smmu->dev, sizeof(*qsmmu), GFP_KERNEL); if (!qsmmu) return ERR_PTR(-ENOMEM); diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 11319e4dce4a..b46dbfa6d0ed 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -986,7 +986,8 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr) warn_invalid_dmar(phys_addr, " returns all ones"); goto unmap; } - iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); + if (ecap_vcs(iommu->ecap)) + iommu->vccap = dmar_readq(iommu->reg + DMAR_VCCAP_REG); /* the registers might be more than one page */ map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index c71a9c279a33..a49afa11673c 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1833,7 +1833,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu) if (ecap_prs(iommu->ecap)) intel_svm_finish_prq(iommu); } - if (ecap_vcs(iommu->ecap) && vccap_pasid(iommu->vccap)) + if (vccap_pasid(iommu->vccap)) ioasid_unregister_allocator(&iommu->pasid_allocator); #endif @@ -3212,7 +3212,7 @@ static void register_pasid_allocator(struct intel_iommu *iommu) * is active. All vIOMMU allocators will eventually be calling the same * host allocator. */ - if (!ecap_vcs(iommu->ecap) || !vccap_pasid(iommu->vccap)) + if (!vccap_pasid(iommu->vccap)) return; pr_info("Register custom PASID allocator\n"); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index b53446bb8c6b..0f4dc25d46c9 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -264,16 +264,18 @@ int iommu_probe_device(struct device *dev) */ iommu_alloc_default_domain(group, dev); - if (group->default_domain) + if (group->default_domain) { ret = __iommu_attach_device(group->default_domain, dev); + if (ret) { + iommu_group_put(group); + goto err_release; + } + } iommu_create_device_direct_mappings(group, dev); iommu_group_put(group); - if (ret) - goto err_release; - if (ops->probe_finalize) ops->probe_finalize(dev); |