diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index e2c914fccd6f..37d31ea11bf6 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -129,6 +129,18 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie, struct arm_smmu_cfg *cfg = &smmu_domain->cfg; struct arm_smmu_device *smmu = smmu_domain->smmu; + /* + * A fault can only fire while the SMMU is active (GPU is issuing + * transactions). Use get_if_active so that if by a rare race the + * device has already suspended, we skip the register reads rather + * than triggering a cold resume which would call device_reset and + * destroy the fault state we are trying to capture. + */ + if (pm_runtime_get_if_active(smmu->dev) <= 0) { + dev_warn(smmu->dev, "get_fault_info: device not active, skipping\n"); + return; + } + info->fsr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSR); info->fsynr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR0); info->fsynr1 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_FSYNR1); @@ -136,6 +148,8 @@ static void qcom_adreno_smmu_get_fault_info(const void *cookie, info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); info->ttbr0 = arm_smmu_cb_readq(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0); info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR); + + pm_runtime_put_autosuspend(smmu->dev); } static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled)