Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecac8a0e authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Cleanup iommu device tree probe"

parents 2e952766 669c1384
Loading
Loading
Loading
Loading
+3 −12
Original line number Diff line number Diff line
@@ -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;
+54 −69
Original line number Diff line number Diff line
@@ -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 {
+4 −2
Original line number Diff line number Diff line
@@ -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;
};

/*
+0 −5
Original line number Diff line number Diff line
@@ -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 */