[PATCH v9 12/12] iommu/arm-smmu-v3: Detect ARM_SMMU_OPT_KDUMP_ADOPT in probe()
Nicolin Chen <[email protected]>
| Newsgroups | dev.linux.lists.iommu,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <629e0eeb1dac857bce3ebcf027938888ab95483f.1784663184.git.nicolinc@nvidia.com> |
arm_smmu_device_hw_probe() runs before arm_smmu_init_structures(), so it's natural to decide whether the kdump kernel must adopt the crashed kernel's stream table. Given that memremap is used to adopt the old stream table, set this option only on a coherent SMMU. And make sure SMMU isn't in Service Failure Mode. Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Pranjal Shrivastava <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 5 ++++ .../iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c | 27 +++++++++++++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 +++ 3 files changed, 36 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index 0bc1de6463785..06146b535a1fc 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -1279,6 +1279,7 @@ int arm_smmu_kdump_adopt_deferred_l2_strtab(struct arm_smmu_device *smmu, u32 sid, phys_addr_t base, u32 span, struct arm_smmu_strtab_l2 **l2table); bool arm_smmu_kdump_is_attach_deferred(struct arm_smmu_master *master); +void arm_smmu_device_kdump_probe(struct arm_smmu_device *smmu); #else /* CONFIG_CRASH_DUMP */ static inline int arm_smmu_kdump_adopt_strtab(struct arm_smmu_device *smmu) { @@ -1298,6 +1299,10 @@ arm_smmu_kdump_is_attach_deferred(struct arm_smmu_master *master) { return false; } + +static inline void arm_smmu_device_kdump_probe(struct arm_smmu_device *smmu) +{ +} #endif /* CONFIG_CRASH_DUMP */ struct arm_vsmmu { diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c index ea7a2bdd77a58..cc52bfdcb30ae 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c @@ -259,3 +259,30 @@ bool arm_smmu_kdump_is_attach_deferred(struct arm_smmu_master *master) return false; } + +void arm_smmu_device_kdump_probe(struct arm_smmu_device *smmu) +{ + u32 gerror, gerrorn, active; + + /* No adoption if SMMU is disabled (i.e., there is no in-flight DMA) */ + if (!(readl_relaxed(smmu->base + ARM_SMMU_CR0) & CR0_SMMUEN)) + return; + + /* For now, only support a coherent SMMU that works with MEMREMAP_WB */ + if (!(smmu->features & ARM_SMMU_FEAT_COHERENCY)) { + dev_warn(smmu->dev, + "non-coherent SMMU unsupported; reset to block all DMAs\n"); + return; + } + + gerror = readl_relaxed(smmu->base + ARM_SMMU_GERROR); + gerrorn = readl_relaxed(smmu->base + ARM_SMMU_GERRORN); + active = gerror ^ gerrorn; + if (active & GERROR_SFM_ERR) { + dev_warn(smmu->dev, + "SMMU in Service Failure Mode, must reset\n"); + return; + } + + smmu->options |= ARM_SMMU_OPT_KDUMP_ADOPT; +} diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 168865af868ad..cfa0991cbd332 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -5257,6 +5257,10 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) dev_info(smmu->dev, "oas %lu-bit (features 0x%08x)\n", smmu->oas, smmu->features); + + if (is_kdump_kernel()) + arm_smmu_device_kdump_probe(smmu); + return 0; } -- 2.43.0