Commit bffb2eaf authored by Rob Clark's avatar Rob Clark Committed by Will Deacon
Browse files

iommu/arm-smmu: Add a way for implementations to influence SCTLR



For the Adreno GPU's SMMU, we want SCTLR.HUPCF set to ensure that
pending translations are not terminated on iova fault.  Otherwise
a terminated CP read could hang the GPU by returning invalid
command-stream data. Add a hook to for the implementation to modify
the sctlr value if it wishes.

Co-developed-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Link: https://lore.kernel.org/r/20201109184728.2463097-3-jcrouse@codeaurora.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 5c7469c6
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -20,6 +20,18 @@ static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
	return container_of(smmu, struct qcom_smmu, smmu);
}

static void qcom_adreno_smmu_write_sctlr(struct arm_smmu_device *smmu, int idx,
		u32 reg)
{
	/*
	 * On the GPU device we want to process subsequent transactions after a
	 * fault to keep the GPU from hanging
	 */
	reg |= ARM_SMMU_SCTLR_HUPCF;

	arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg);
}

#define QCOM_ADRENO_SMMU_GPU_SID 0

static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
@@ -289,6 +301,7 @@ static const struct arm_smmu_impl qcom_adreno_smmu_impl = {
	.def_domain_type = qcom_smmu_def_domain_type,
	.reset = qcom_smmu500_reset,
	.alloc_context_bank = qcom_adreno_smmu_alloc_context_bank,
	.write_sctlr = qcom_adreno_smmu_write_sctlr,
};

static struct arm_smmu_device *qcom_smmu_create(struct arm_smmu_device *smmu,
+4 −1
Original line number Diff line number Diff line
@@ -617,6 +617,9 @@ void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx)
	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
		reg |= ARM_SMMU_SCTLR_E;

	if (smmu->impl && smmu->impl->write_sctlr)
		smmu->impl->write_sctlr(smmu, idx, reg);
	else
		arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg);
}

+2 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ enum arm_smmu_cbar_type {
#define ARM_SMMU_CB_SCTLR		0x0
#define ARM_SMMU_SCTLR_S1_ASIDPNE	BIT(12)
#define ARM_SMMU_SCTLR_CFCFG		BIT(7)
#define ARM_SMMU_SCTLR_HUPCF		BIT(8)
#define ARM_SMMU_SCTLR_CFIE		BIT(6)
#define ARM_SMMU_SCTLR_CFRE		BIT(5)
#define ARM_SMMU_SCTLR_E		BIT(4)
@@ -437,6 +438,7 @@ struct arm_smmu_impl {
				  struct arm_smmu_device *smmu,
				  struct device *dev, int start);
	void (*write_s2cr)(struct arm_smmu_device *smmu, int idx);
	void (*write_sctlr)(struct arm_smmu_device *smmu, int idx, u32 reg);
};

#define INVALID_SMENDX			-1