From 669c13845dca10fa058fd16430803f69bba1b16c Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:04 -0600 Subject: [PATCH] msm: kgsl: Cleanup iommu device tree probe We only ever have two sub-devices for IOMMU, one device for the user context and an optional entry for the secure context. Instead of blindly querying for compatibles and try to match the string names, explicitly search for the device names we need and set them up that way. This cleanup also lets us swap the behavior of the mmu.secured flag. We assume it to be true and then clear it if the secure context is not found rather than the other way around. This allows us to make sure that the flag is set correctly during probe so we can skip secure context setup. Change-Id: Ic0dedbad540733a1eaf1729ddec0031f397d9e43 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 15 +---- drivers/gpu/msm/kgsl_iommu.c | 123 +++++++++++++++-------------------- drivers/gpu/msm/kgsl_iommu.h | 6 +- drivers/gpu/msm/kgsl_mmu.h | 5 -- 4 files changed, 61 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 63dc0e883873..cd0154a78b85 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1404,6 +1404,9 @@ static int adreno_probe(struct platform_device *pdev) device->pwrctrl.bus_width = adreno_dev->gpucore->bus_width; + device->mmu.secured = (IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) && + ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)); + status = kgsl_device_platform_probe(device); if (status) { device->pdev = NULL; @@ -1419,18 +1422,6 @@ static int adreno_probe(struct platform_device *pdev) adreno_rscc_probe(device); adreno_isense_probe(device); - /* - * qcom,iommu-secure-id is used to identify MMUs that can handle secure - * content but that is only part of the story - the GPU also has to be - * able to handle secure content. Unfortunately in a classic catch-22 - * we cannot identify the GPU until after the DT is parsed. tl;dr - - * check the GPU capabilities here and modify mmu->secured accordingly - */ - -#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) - if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) - device->mmu.secured = false; -#endif if (ADRENO_FEATURE(adreno_dev, ADRENO_IOCOHERENT)) device->mmu.features |= KGSL_MMU_IO_COHERENT; diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 58c6e62e73b7..62b8e7cbaad4 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -135,7 +135,7 @@ static void _detach_pt(struct kgsl_iommu_pt *iommu_pt, struct kgsl_iommu_context *ctx) { if (iommu_pt->attached) { - iommu_detach_device(iommu_pt->domain, ctx->dev); + iommu_detach_device(iommu_pt->domain, &ctx->pdev->dev); iommu_pt->attached = false; } } @@ -148,7 +148,7 @@ static int _attach_pt(struct kgsl_iommu_pt *iommu_pt, if (iommu_pt->attached) return 0; - ret = iommu_attach_device(iommu_pt->domain, ctx->dev); + ret = iommu_attach_device(iommu_pt->domain, &ctx->pdev->dev); if (ret == 0) iommu_pt->attached = true; @@ -935,7 +935,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER]; - iommu_pt = _alloc_pt(ctx->dev, mmu, pt); + iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt); if (IS_ERR(iommu_pt)) return PTR_ERR(iommu_pt); @@ -1016,7 +1016,7 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) if (!mmu->secured) return -EPERM; - iommu_pt = _alloc_pt(ctx->dev, mmu, pt); + iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt); if (IS_ERR(iommu_pt)) return PTR_ERR(iommu_pt); @@ -1058,7 +1058,7 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) int dynamic = 1; unsigned int cb_num = ctx->cb_num; - iommu_pt = _alloc_pt(ctx->dev, mmu, pt); + iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt); if (IS_ERR(iommu_pt)) return PTR_ERR(iommu_pt); @@ -1165,6 +1165,9 @@ static void _detach_context(struct kgsl_iommu_context *ctx) _detach_pt(iommu_pt, ctx); ctx->default_pt = NULL; + platform_device_put(ctx->pdev); + + ctx->pdev = NULL; } static void kgsl_iommu_close(struct kgsl_mmu *mmu) @@ -1196,6 +1199,9 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu) __free_page(kgsl_dummy_page); kgsl_dummy_page = NULL; } + + of_platform_depopulate(&iommu->pdev->dev); + platform_device_put(iommu->pdev); } static int kgsl_iommu_init(struct kgsl_mmu *mmu) @@ -1332,7 +1338,7 @@ static int _setup_secure_context(struct kgsl_mmu *mmu) struct kgsl_iommu_pt *iommu_pt; - if (ctx->dev == NULL || !mmu->secured) + if (!ctx->pdev || !mmu->secured) return 0; if (mmu->securepagetable == NULL) @@ -2229,65 +2235,37 @@ static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable, return false; } -static const struct { - int id; - char *name; -} kgsl_iommu_cbs[] = { - { KGSL_IOMMU_CONTEXT_USER, "gfx3d_user", }, - { KGSL_IOMMU_CONTEXT_SECURE, "gfx3d_secure" }, - { KGSL_IOMMU_CONTEXT_SECURE, "gfx3d_secure_alt" }, -}; - -static int _kgsl_iommu_cb_probe(struct kgsl_device *device, - struct kgsl_iommu *iommu, struct device_node *node) +static int kgsl_iommu_probe_child(struct kgsl_device *device, + struct device_node *parent, int id, const char *name) { - struct platform_device *pdev = of_find_device_by_node(node); - struct kgsl_iommu_context *ctx = NULL; - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - int i; + struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); + struct device_node *node = of_find_node_by_name(parent, name); + struct platform_device *pdev; + struct device_node *phandle; - for (i = 0; i < ARRAY_SIZE(kgsl_iommu_cbs); i++) { - if (!strcmp(node->name, kgsl_iommu_cbs[i].name)) { - int id = kgsl_iommu_cbs[i].id; + if (!node) + return -ENOENT; - if (ADRENO_QUIRK(adreno_dev, - ADRENO_QUIRK_MMU_SECURE_CB_ALT)) { - if (!strcmp(node->name, "gfx3d_secure")) - continue; - } else if (!strcmp(node->name, "gfx3d_secure_alt")) - continue; + pdev = of_find_device_by_node(node); - ctx = &iommu->ctx[id]; - ctx->id = id; - ctx->cb_num = -1; - ctx->name = kgsl_iommu_cbs[i].name; + iommu->ctx[id].id = id; + iommu->ctx[id].cb_num = -1; + iommu->ctx[id].name = name; - break; - } - } + iommu->ctx[id].kgsldev = device; - if (ctx == NULL) { - dev_info(device->dev, - "dt: Unused context label %s\n", node->name); - return 0; - } + iommu->ctx[id].pdev = pdev; - if (ctx->id == KGSL_IOMMU_CONTEXT_SECURE) - device->mmu.secured = true; + phandle = of_parse_phandle(node, "iommus", 0); - ctx->kgsldev = device; + if (phandle && of_device_is_compatible(phandle, "qcom,qsmmu-v500")) + device->mmu.subtype = KGSL_IOMMU_SMMU_V500; - /* arm-smmu driver we'll have the right device pointer here. */ - if (of_find_property(node, "iommus", NULL)) { - ctx->dev = &pdev->dev; - } else { - ctx->dev = kgsl_mmu_get_ctx(ctx->name); + of_node_put(phandle); - if (IS_ERR(ctx->dev)) - return PTR_ERR(ctx->dev); - } + of_dma_configure(&pdev->dev, node, true); - of_dma_configure(ctx->dev, node, true); + of_node_put(node); return 0; } @@ -2305,13 +2283,15 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, const char *cname; struct property *prop; u32 reg_val[2]; - int i = 0; + int i = 0, ret; struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); - struct device_node *child, *iommu_node = NULL; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct platform_device *pdev = of_find_device_by_node(node); memset(iommu, 0, sizeof(*iommu)); + iommu->pdev = pdev; + if (of_property_read_u32_array(node, "reg", reg_val, 2)) { dev_err(device->dev, "dt: Unable to read KGSL IOMMU register range\n"); @@ -2326,10 +2306,12 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, if (IS_ERR(c)) { dev_err(device->dev, "dt: Couldn't get clock: %s\n", cname); + platform_device_put(pdev); return -ENODEV; } if (i >= KGSL_IOMMU_MAX_CLKS) { dev_err(device->dev, "dt: too many clocks defined.\n"); + platform_device_put(pdev); return -EINVAL; } @@ -2345,25 +2327,28 @@ static int _kgsl_iommu_probe(struct kgsl_device *device, /* Fill out the rest of the devices in the node */ of_platform_populate(node, NULL, NULL, &pdev->dev); - for_each_child_of_node(node, child) { - int ret; + /* The "user" device always needs to be present */ + ret = kgsl_iommu_probe_child(device, node, KGSL_IOMMU_CONTEXT_USER, + "gfx3d_user"); - if (!of_device_is_compatible(child, "qcom,smmu-kgsl-cb")) - continue; + if (!ret && device->mmu.secured) { + const char *name = "gfx3d_secure"; - ret = _kgsl_iommu_cb_probe(device, iommu, child); - if (ret) - return ret; + if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_MMU_SECURE_CB_ALT)) + name = "gfx3d_secure_alt"; - if (!iommu_node) - iommu_node = of_parse_phandle(child, "iommus", 0); + /* Secure context bank devices are optional */ + if (kgsl_iommu_probe_child(device, node, + KGSL_IOMMU_CONTEXT_SECURE, name)) + device->mmu.secured = false; } - if (iommu_node && - of_device_is_compatible(iommu_node, "qcom,qsmmu-v500")) - device->mmu.subtype = KGSL_IOMMU_SMMU_V500; + if (ret) { + of_platform_depopulate(&pdev->dev); + platform_device_put(pdev); + } - return 0; + return ret; } static const struct { diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index 1fea16929b95..8b4f7e3952b7 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -80,7 +80,7 @@ enum kgsl_iommu_context_id { /* * struct kgsl_iommu_context - Structure holding data about an iommu context * bank - * @dev: pointer to the iommu context's device + * @pdev: pointer to the iommu context's platform device * @name: context name * @id: The id of the context, used for deciding how it is used. * @cb_num: The hardware context bank number, used for calculating register @@ -92,7 +92,7 @@ enum kgsl_iommu_context_id { * it may be changed by self programming. */ struct kgsl_iommu_context { - struct device *dev; + struct platform_device *pdev; const char *name; enum kgsl_iommu_context_id id; unsigned int cb_num; @@ -122,6 +122,8 @@ struct kgsl_iommu { atomic_t clk_enable_count; struct clk *clks[KGSL_IOMMU_MAX_CLKS]; struct kgsl_memdesc *smmu_info; + /** @pdev: Pointer to the platform device for the IOMMU device */ + struct platform_device *pdev; }; /* diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index 827b28d9b095..952dbb70b3b4 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -344,9 +344,4 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable) */ u64 kgsl_mmu_get_global_base(struct kgsl_device *device); -static inline struct device *kgsl_mmu_get_ctx(const char *name) -{ - return ERR_PTR(-ENODEV); -} - #endif /* __KGSL_MMU_H */