Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu/arm-smmu-qcom: Add stall support

Add, via the adreno-smmu-priv interface, a way for the GPU to request
the SMMU to stall translation on faults, and then later resume the
translation, either retrying or terminating the current translation.

This will be used on the GPU side to "freeze" the GPU while we snapshot
useful state for devcoredump.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Acked-by: Jordan Crouse <jordan@cosmicpenguin.net>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20210610214431.539029-5-robdclark@gmail.com
Signed-off-by: Rob Clark <robdclark@chromium.org>

+40
+33
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
··· 13 13 struct arm_smmu_device smmu; 14 14 bool bypass_quirk; 15 15 u8 bypass_cbndx; 16 + u32 stall_enabled; 16 17 }; 17 18 18 19 static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu) ··· 24 23 static void qcom_adreno_smmu_write_sctlr(struct arm_smmu_device *smmu, int idx, 25 24 u32 reg) 26 25 { 26 + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu); 27 + 27 28 /* 28 29 * On the GPU device we want to process subsequent transactions after a 29 30 * fault to keep the GPU from hanging 30 31 */ 31 32 reg |= ARM_SMMU_SCTLR_HUPCF; 33 + 34 + if (qsmmu->stall_enabled & BIT(idx)) 35 + reg |= ARM_SMMU_SCTLR_CFCFG; 32 36 33 37 arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg); 34 38 } ··· 52 46 info->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); 53 47 info->ttbr0 = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_TTBR0); 54 48 info->contextidr = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_CONTEXTIDR); 49 + } 50 + 51 + static void qcom_adreno_smmu_set_stall(const void *cookie, bool enabled) 52 + { 53 + struct arm_smmu_domain *smmu_domain = (void *)cookie; 54 + struct arm_smmu_cfg *cfg = &smmu_domain->cfg; 55 + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu); 56 + 57 + if (enabled) 58 + qsmmu->stall_enabled |= BIT(cfg->cbndx); 59 + else 60 + qsmmu->stall_enabled &= ~BIT(cfg->cbndx); 61 + } 62 + 63 + static void qcom_adreno_smmu_resume_translation(const void *cookie, bool terminate) 64 + { 65 + struct arm_smmu_domain *smmu_domain = (void *)cookie; 66 + struct arm_smmu_cfg *cfg = &smmu_domain->cfg; 67 + struct arm_smmu_device *smmu = smmu_domain->smmu; 68 + u32 reg = 0; 69 + 70 + if (terminate) 71 + reg |= ARM_SMMU_RESUME_TERMINATE; 72 + 73 + arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_RESUME, reg); 55 74 } 56 75 57 76 #define QCOM_ADRENO_SMMU_GPU_SID 0 ··· 204 173 priv->get_ttbr1_cfg = qcom_adreno_smmu_get_ttbr1_cfg; 205 174 priv->set_ttbr0_cfg = qcom_adreno_smmu_set_ttbr0_cfg; 206 175 priv->get_fault_info = qcom_adreno_smmu_get_fault_info; 176 + priv->set_stall = qcom_adreno_smmu_set_stall; 177 + priv->resume_translation = qcom_adreno_smmu_resume_translation; 207 178 208 179 return 0; 209 180 }
+7
include/linux/adreno-smmu-priv.h
··· 45 45 * TTBR0 translation is enabled with the specified cfg 46 46 * @get_fault_info: Called by the GPU fault handler to get information about 47 47 * the fault 48 + * @set_stall: Configure whether stall on fault (CFCFG) is enabled. Call 49 + * before set_ttbr0_cfg(). If stalling on fault is enabled, 50 + * the GPU driver must call resume_translation() 51 + * @resume_translation: Resume translation after a fault 52 + * 48 53 * 49 54 * The GPU driver (drm/msm) and adreno-smmu work together for controlling 50 55 * the GPU's SMMU instance. This is by necessity, as the GPU is directly ··· 65 60 const struct io_pgtable_cfg *(*get_ttbr1_cfg)(const void *cookie); 66 61 int (*set_ttbr0_cfg)(const void *cookie, const struct io_pgtable_cfg *cfg); 67 62 void (*get_fault_info)(const void *cookie, struct adreno_smmu_fault_info *info); 63 + void (*set_stall)(const void *cookie, bool enabled); 64 + void (*resume_translation)(const void *cookie, bool terminate); 68 65 }; 69 66 70 67 #endif /* __ADRENO_SMMU_PRIV_H */