From: AngeloGioacchino Del Regno <angelogioacchino.delregno@xxxxxxxxxxxxxx> This driver was indexing the contexts by asid-1, which is probably done under the assumption that the first ASID is always 1. Unfortunately this is not entirely true: at least in the MSM8956 and MSM8976 GPU IOMMU, the gpu_user context's ASID number is zero. To allow using an asid number of zero, stop indexing the contexts by asid-1 and rather index them by asid. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@xxxxxxxxxxxxxx> Signed-off-by: Marijn Suijten <marijn.suijten@xxxxxxxxxxxxxx> Signed-off-by: Konrad Dybcio <konrad.dybcio@xxxxxxxxxxxxxx> --- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c index 530aa92bf6a1..4fefbab15b71 100644 --- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c +++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c @@ -53,7 +53,7 @@ struct qcom_iommu_dev { u32 sec_id; u8 num_ctxs; bool use_aarch64_pt; - struct qcom_iommu_ctx *ctxs[]; /* indexed by asid-1 */ + struct qcom_iommu_ctx *ctxs[]; /* indexed by asid */ }; struct qcom_iommu_ctx { @@ -95,7 +95,7 @@ static struct qcom_iommu_ctx * to_ctx(struct qcom_iommu_domain *d, unsigned asid struct qcom_iommu_dev *qcom_iommu = d->iommu; if (!qcom_iommu) return NULL; - return qcom_iommu->ctxs[asid - 1]; + return qcom_iommu->ctxs[asid]; } static inline void @@ -614,12 +614,10 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args) qcom_iommu = platform_get_drvdata(iommu_pdev); /* make sure the asid specified in dt is valid, so we don't have - * to sanity check this elsewhere, since 'asid - 1' is used to - * index into qcom_iommu->ctxs: + * to sanity check this elsewhere: */ - if (WARN_ON(asid < 1) || - WARN_ON(asid > qcom_iommu->num_ctxs) || - WARN_ON(qcom_iommu->ctxs[asid - 1] == NULL)) { + if (WARN_ON(asid >= qcom_iommu->num_ctxs) || + WARN_ON(qcom_iommu->ctxs[asid] == NULL)) { put_device(&iommu_pdev->dev); return -EINVAL; } @@ -778,7 +776,7 @@ static int qcom_iommu_ctx_probe(struct platform_device *pdev) dev_dbg(dev, "found asid %u\n", ctx->asid); - qcom_iommu->ctxs[ctx->asid - 1] = ctx; + qcom_iommu->ctxs[ctx->asid] = ctx; return 0; } @@ -790,7 +788,7 @@ static int qcom_iommu_ctx_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - qcom_iommu->ctxs[ctx->asid - 1] = NULL; + qcom_iommu->ctxs[ctx->asid] = NULL; return 0; } @@ -828,7 +826,7 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; struct clk *clk; - int ret, max_asid = 0; + int ret, num_ctxs, max_asid = 0; /* find the max asid (which is 1:1 to ctx bank idx), so we know how * many child ctx devices we have: @@ -836,11 +834,13 @@ static int qcom_iommu_device_probe(struct platform_device *pdev) for_each_child_of_node(dev->of_node, child) max_asid = max(max_asid, get_asid(child)); - qcom_iommu = devm_kzalloc(dev, struct_size(qcom_iommu, ctxs, max_asid), + num_ctxs = max_asid + 1; + + qcom_iommu = devm_kzalloc(dev, struct_size(qcom_iommu, ctxs, num_ctxs), GFP_KERNEL); if (!qcom_iommu) return -ENOMEM; - qcom_iommu->num_ctxs = max_asid; + qcom_iommu->num_ctxs = num_ctxs; qcom_iommu->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- 2.36.1