All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/msm: Initialize MDSS irq domain at probe time
@ 2021-11-25 15:09 ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 30+ messages in thread
From: AngeloGioacchino Del Regno @ 2021-11-25 15:09 UTC (permalink / raw)
  To: robdclark
  Cc: freedreno, airlied, linux-arm-msm, konrad.dybcio, linux-kernel,
	dri-devel, jami.kettunen, maxime, marijn.suijten, kernel, sean,
	AngeloGioacchino Del Regno

Since commit 8f59ee9a570c ("drm/msm/dsi: Adjust probe order"), the
DSI host gets initialized earlier, but this caused unability to probe
the entire stack of components because they all depend on interrupts
coming from the main `mdss` node (mdp5, or dpu1).

To fix this issue, also anticipate probing mdp5 or dpu1 by initializing
them at msm_pdev_probe() time: this will make sure that we add the
required interrupt controller mapping before dsi and/or other components
try to initialize, finally satisfying the dependency.

While at it, also change the allocation of msm_drm_private to use the
devm variant of kzalloc().

Fixes: 8f59ee9a570c ("drm/msm/dsi: Adjust probe order")
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/msm/msm_drv.c | 81 ++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7936e8d498dd..790acf4993c0 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -512,45 +512,12 @@ static int msm_init_vram(struct drm_device *dev)
 static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct drm_device *ddev;
-	struct msm_drm_private *priv;
-	struct msm_kms *kms;
-	struct msm_mdss *mdss;
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = ddev->dev_private;
+	struct msm_kms *kms = priv->kms;
+	struct msm_mdss *mdss = priv->mdss;
 	int ret, i;
 
-	ddev = drm_dev_alloc(drv, dev);
-	if (IS_ERR(ddev)) {
-		DRM_DEV_ERROR(dev, "failed to allocate drm_device\n");
-		return PTR_ERR(ddev);
-	}
-
-	platform_set_drvdata(pdev, ddev);
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		ret = -ENOMEM;
-		goto err_put_drm_dev;
-	}
-
-	ddev->dev_private = priv;
-	priv->dev = ddev;
-
-	switch (get_mdp_ver(pdev)) {
-	case KMS_MDP5:
-		ret = mdp5_mdss_init(ddev);
-		break;
-	case KMS_DPU:
-		ret = dpu_mdss_init(ddev);
-		break;
-	default:
-		ret = 0;
-		break;
-	}
-	if (ret)
-		goto err_free_priv;
-
-	mdss = priv->mdss;
-
 	priv->wq = alloc_ordered_workqueue("msm", 0);
 	priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;
 
@@ -685,11 +652,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
 err_destroy_mdss:
 	if (mdss && mdss->funcs)
 		mdss->funcs->destroy(ddev);
-err_free_priv:
-	kfree(priv);
-err_put_drm_dev:
-	drm_dev_put(ddev);
-	platform_set_drvdata(pdev, NULL);
 	return ret;
 }
 
@@ -1382,12 +1344,42 @@ static const struct component_master_ops msm_drm_ops = {
 static int msm_pdev_probe(struct platform_device *pdev)
 {
 	struct component_match *match = NULL;
+	struct msm_drm_private *priv;
+	struct drm_device *ddev;
 	int ret;
 
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ddev = drm_dev_alloc(&msm_driver, &pdev->dev);
+	if (IS_ERR(ddev)) {
+		DRM_DEV_ERROR(&pdev->dev, "failed to allocate drm_device\n");
+		return PTR_ERR(ddev);
+	}
+
+	platform_set_drvdata(pdev, ddev);
+	ddev->dev_private = priv;
+	priv->dev = ddev;
+
+	switch (get_mdp_ver(pdev)) {
+	case KMS_MDP5:
+		ret = mdp5_mdss_init(ddev);
+		break;
+	case KMS_DPU:
+		ret = dpu_mdss_init(ddev);
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	if (ret)
+		goto err_put_drm_dev;
+
 	if (get_mdp_ver(pdev)) {
 		ret = add_display_components(pdev, &match);
 		if (ret)
-			return ret;
+			goto fail;
 	}
 
 	ret = add_gpu_components(&pdev->dev, &match);
@@ -1409,6 +1401,9 @@ static int msm_pdev_probe(struct platform_device *pdev)
 
 fail:
 	of_platform_depopulate(&pdev->dev);
+err_put_drm_dev:
+	drm_dev_put(ddev);
+	platform_set_drvdata(pdev, NULL);
 	return ret;
 }
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread
* [PATCH v3 2/2] drm/msm: Initialize MDSS irq domain at probe time
@ 2021-12-01 10:52 AngeloGioacchino Del Regno
  2021-12-01 20:20   ` Dmitry Baryshkov
  0 siblings, 1 reply; 30+ messages in thread
From: AngeloGioacchino Del Regno @ 2021-12-01 10:52 UTC (permalink / raw)
  To: robdclark
  Cc: dmitry.baryshkov, sean, airlied, daniel, maxime, linux-arm-msm,
	dri-devel, freedreno, linux-kernel, kernel, konrad.dybcio,
	marijn.suijten, jami.kettunen, martin.botka,
	AngeloGioacchino Del Regno

Since commit 8f59ee9a570c ("drm/msm/dsi: Adjust probe order"), the
DSI host gets initialized earlier, but this caused unability to probe
the entire stack of components because they all depend on interrupts
coming from the main `mdss` node (mdp5, or dpu1).

To fix this issue, anticipate registering the irq domain from mdp5/dpu1
at msm_mdev_probe() time, as to make sure that the interrupt controller
is available before dsi and/or other components try to initialize,
finally satisfying the dependency.

Moreover, to balance this operation while avoiding to always check if
the irq domain is registered everytime we call bind() on msm_pdev, add
a new *remove function pointer to msm_mdss_funcs, used to remove the
irq domain only at msm_pdev_remove() time.

Fixes: 8f59ee9a570c ("drm/msm/dsi: Adjust probe order")
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c  | 50 ++++++++++++-------
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 58 +++++++++++++++--------
 drivers/gpu/drm/msm/msm_drv.c             | 22 ++++++++-
 drivers/gpu/drm/msm/msm_kms.h             |  3 ++
 4 files changed, 95 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index b466784d9822..6c2569175633 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -106,13 +106,10 @@ static const struct irq_domain_ops dpu_mdss_irqdomain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
-static int _dpu_mdss_irq_domain_add(struct dpu_mdss *dpu_mdss)
+static int _dpu_mdss_irq_domain_add(struct device *dev, struct dpu_mdss *dpu_mdss)
 {
-	struct device *dev;
 	struct irq_domain *domain;
 
-	dev = dpu_mdss->base.dev->dev;
-
 	domain = irq_domain_add_linear(dev->of_node, 32,
 			&dpu_mdss_irqdomain_ops, dpu_mdss);
 	if (!domain) {
@@ -194,7 +191,6 @@ static void dpu_mdss_destroy(struct drm_device *dev)
 
 	pm_runtime_suspend(dev->dev);
 	pm_runtime_disable(dev->dev);
-	_dpu_mdss_irq_domain_fini(dpu_mdss);
 	irq = platform_get_irq(pdev, 0);
 	irq_set_chained_handler_and_data(irq, NULL, NULL);
 	msm_dss_put_clk(mp->clk_config, mp->num_clk);
@@ -203,15 +199,43 @@ static void dpu_mdss_destroy(struct drm_device *dev)
 	if (dpu_mdss->mmio)
 		devm_iounmap(&pdev->dev, dpu_mdss->mmio);
 	dpu_mdss->mmio = NULL;
-	priv->mdss = NULL;
+}
+
+static void dpu_mdss_remove(struct msm_mdss *mdss)
+{
+	_dpu_mdss_irq_domain_fini(to_dpu_mdss(mdss));
 }
 
 static const struct msm_mdss_funcs mdss_funcs = {
 	.enable	= dpu_mdss_enable,
 	.disable = dpu_mdss_disable,
 	.destroy = dpu_mdss_destroy,
+	.remove = dpu_mdss_remove,
 };
 
+int dpu_mdss_early_init(struct device *dev, struct msm_drm_private *priv)
+{
+	struct dpu_mdss *dpu_mdss;
+	int ret;
+
+	dpu_mdss = devm_kzalloc(dev, sizeof(*dpu_mdss), GFP_KERNEL);
+	if (!dpu_mdss)
+		return -ENOMEM;
+
+	ret = _dpu_mdss_irq_domain_add(dev, dpu_mdss);
+	if (ret)
+		return ret;
+
+	/*
+	 * Here we have no drm_device yet, but still do the assignment
+	 * so that we can retrieve our struct dpu_mdss from the main
+	 * init function, since we allocate it here.
+	 */
+	priv->mdss = &dpu_mdss->base;
+
+	return 0;
+}
+
 int dpu_mdss_init(struct drm_device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev->dev);
@@ -221,9 +245,9 @@ int dpu_mdss_init(struct drm_device *dev)
 	int ret;
 	int irq;
 
-	dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
+	dpu_mdss = to_dpu_mdss(priv->mdss);
 	if (!dpu_mdss)
-		return -ENOMEM;
+		return -ENODATA;
 
 	dpu_mdss->mmio = msm_ioremap(pdev, "mdss", "mdss");
 	if (IS_ERR(dpu_mdss->mmio))
@@ -241,10 +265,6 @@ int dpu_mdss_init(struct drm_device *dev)
 	dpu_mdss->base.dev = dev;
 	dpu_mdss->base.funcs = &mdss_funcs;
 
-	ret = _dpu_mdss_irq_domain_add(dpu_mdss);
-	if (ret)
-		goto irq_domain_error;
-
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		ret = irq;
@@ -253,16 +273,10 @@ int dpu_mdss_init(struct drm_device *dev)
 
 	irq_set_chained_handler_and_data(irq, dpu_mdss_irq,
 					 dpu_mdss);
-
-	priv->mdss = &dpu_mdss->base;
-
 	pm_runtime_enable(dev->dev);
-
 	return 0;
 
 irq_error:
-	_dpu_mdss_irq_domain_fini(dpu_mdss);
-irq_domain_error:
 	msm_dss_put_clk(mp->clk_config, mp->num_clk);
 clk_parse_err:
 	devm_kfree(&pdev->dev, mp->clk_config);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
index 0ea53420bc40..a99538ae4182 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c
@@ -112,9 +112,8 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = {
 };
 
 
-static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss)
+static int mdss_irq_domain_init(struct device *dev, struct mdp5_mdss *mdp5_mdss)
 {
-	struct device *dev = mdp5_mdss->base.dev->dev;
 	struct irq_domain *d;
 
 	d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops,
@@ -182,20 +181,52 @@ static void mdp5_mdss_destroy(struct drm_device *dev)
 	if (!mdp5_mdss)
 		return;
 
-	irq_domain_remove(mdp5_mdss->irqcontroller.domain);
-	mdp5_mdss->irqcontroller.domain = NULL;
-
 	regulator_disable(mdp5_mdss->vdd);
 
 	pm_runtime_disable(dev->dev);
 }
 
+static void mdp5_mdss_remove(struct msm_mdss *mdss)
+{
+	struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss);
+
+	irq_domain_remove(mdp5_mdss->irqcontroller.domain);
+	mdp5_mdss->irqcontroller.domain = NULL;
+}
+
 static const struct msm_mdss_funcs mdss_funcs = {
 	.enable	= mdp5_mdss_enable,
 	.disable = mdp5_mdss_disable,
 	.destroy = mdp5_mdss_destroy,
+	.remove = mdp5_mdss_remove,
 };
 
+int mdp5_mdss_early_init(struct device *dev, struct msm_drm_private *priv)
+{
+	struct mdp5_mdss *mdp5_mdss;
+	int ret;
+
+	if (!of_device_is_compatible(dev->of_node, "qcom,mdss"))
+		return 0;
+
+	mdp5_mdss = devm_kzalloc(dev, sizeof(*mdp5_mdss), GFP_KERNEL);
+	if (!mdp5_mdss)
+		return -ENOMEM;
+
+	ret = mdss_irq_domain_init(dev, mdp5_mdss);
+	if (ret)
+		return ret;
+
+	/*
+	 * Here we have no drm_device yet, but still do the assignment
+	 * so that we can retrieve our struct mdp5_mdss from the main
+	 * init function, since we allocate it here.
+	 */
+	priv->mdss = &mdp5_mdss->base;
+
+	return 0;
+}
+
 int mdp5_mdss_init(struct drm_device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev->dev);
@@ -208,11 +239,9 @@ int mdp5_mdss_init(struct drm_device *dev)
 	if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss"))
 		return 0;
 
-	mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL);
-	if (!mdp5_mdss) {
-		ret = -ENOMEM;
-		goto fail;
-	}
+	mdp5_mdss = to_mdp5_mdss(priv->mdss);
+	if (!mdp5_mdss)
+		return -ENODATA;
 
 	mdp5_mdss->base.dev = dev;
 
@@ -255,17 +284,8 @@ int mdp5_mdss_init(struct drm_device *dev)
 		goto fail_irq;
 	}
 
-	ret = mdss_irq_domain_init(mdp5_mdss);
-	if (ret) {
-		DRM_DEV_ERROR(dev->dev, "failed to init sub-block irqs: %d\n", ret);
-		goto fail_irq;
-	}
-
 	mdp5_mdss->base.funcs = &mdss_funcs;
-	priv->mdss = &mdp5_mdss->base;
-
 	pm_runtime_enable(dev->dev);
-
 	return 0;
 fail_irq:
 	regulator_disable(mdp5_mdss->vdd);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 64230e473a34..ded4f4d6545f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1389,6 +1389,20 @@ static int msm_pdev_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
+	switch (get_mdp_ver(pdev)) {
+	case KMS_MDP5:
+		ret = mdp5_mdss_early_init(&pdev->dev, priv);
+		break;
+	case KMS_DPU:
+		ret = dpu_mdss_early_init(&pdev->dev, priv);
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	if (ret)
+		return ret;
+
 	platform_set_drvdata(pdev, priv);
 
 	if (get_mdp_ver(pdev)) {
@@ -1421,6 +1435,12 @@ static int msm_pdev_probe(struct platform_device *pdev)
 
 static int msm_pdev_remove(struct platform_device *pdev)
 {
+	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+
+	if (priv->mdss && priv->mdss->funcs)
+		priv->mdss->funcs->remove(priv->mdss);
+
+	priv->mdss = NULL;
 	component_master_del(&pdev->dev, &msm_drm_ops);
 	of_platform_depopulate(&pdev->dev);
 
@@ -1432,7 +1452,7 @@ static void msm_pdev_shutdown(struct platform_device *pdev)
 	struct msm_drm_private *priv = platform_get_drvdata(pdev);
 	struct drm_device *drm = priv ? priv->dev : NULL;
 
-	if (!priv || !priv->kms)
+	if (!priv || !priv->kms || !drm->mode_config.funcs)
 		return;
 
 	drm_atomic_helper_shutdown(drm);
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 6a42b819abc4..2c539a228156 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -202,6 +202,7 @@ struct msm_mdss_funcs {
 	int (*enable)(struct msm_mdss *mdss);
 	int (*disable)(struct msm_mdss *mdss);
 	void (*destroy)(struct drm_device *dev);
+	void (*remove)(struct msm_mdss *mdss);
 };
 
 struct msm_mdss {
@@ -209,7 +210,9 @@ struct msm_mdss {
 	const struct msm_mdss_funcs *funcs;
 };
 
+int mdp5_mdss_early_init(struct device *dev, struct msm_drm_private *priv);
 int mdp5_mdss_init(struct drm_device *dev);
+int dpu_mdss_early_init(struct device *dev, struct msm_drm_private *priv);
 int dpu_mdss_init(struct drm_device *dev);
 
 #define for_each_crtc_mask(dev, crtc, crtc_mask) \
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2021-12-03 13:17 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-25 15:09 [PATCH] drm/msm: Initialize MDSS irq domain at probe time AngeloGioacchino Del Regno
2021-11-25 15:09 ` AngeloGioacchino Del Regno
2021-11-25 15:23 ` Dmitry Baryshkov
2021-11-25 15:23   ` Dmitry Baryshkov
2021-11-25 22:39 ` Dmitry Baryshkov
2021-11-25 22:39   ` Dmitry Baryshkov
2021-11-26  0:06 ` Dmitry Baryshkov
2021-11-26  0:06   ` Dmitry Baryshkov
2021-11-26  9:26   ` AngeloGioacchino Del Regno
2021-11-26  9:26     ` AngeloGioacchino Del Regno
2021-11-26 21:12     ` Dmitry Baryshkov
2021-11-26 21:12       ` Dmitry Baryshkov
2021-11-26 16:08   ` AngeloGioacchino Del Regno
2021-11-26 16:08     ` AngeloGioacchino Del Regno
2021-11-29  2:20 ` Dmitry Baryshkov
2021-11-29  2:20   ` Dmitry Baryshkov
2021-11-29 14:14   ` AngeloGioacchino Del Regno
2021-11-29 14:14     ` AngeloGioacchino Del Regno
2021-11-29 14:53     ` Dmitry Baryshkov
2021-11-29 14:53       ` Dmitry Baryshkov
2021-11-29 14:56       ` AngeloGioacchino Del Regno
2021-11-29 14:56         ` AngeloGioacchino Del Regno
2021-12-01 10:52 [PATCH v3 2/2] " AngeloGioacchino Del Regno
2021-12-01 20:20 ` [PATCH] " Dmitry Baryshkov
2021-12-01 20:20   ` Dmitry Baryshkov
2021-12-03 10:43   ` AngeloGioacchino Del Regno
2021-12-03 10:43     ` AngeloGioacchino Del Regno
2021-12-03 13:14     ` Dmitry Baryshkov
2021-12-03 13:14       ` Dmitry Baryshkov
2021-12-03 13:17       ` AngeloGioacchino Del Regno
2021-12-03 13:17         ` AngeloGioacchino Del Regno

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.