All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-01-31  8:55 ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-01-31  8:55 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-mediatek, linux-arm-kernel, linux-kernel, chunkuang.hu,
	p.zabel, airlied, daniel, matthias.bgg, kernel, andrzej.hajda,
	AngeloGioacchino Del Regno, stable, Jagan Teki

DRM bridge drivers are now attaching their DSI device at probe time,
which requires us to register our DSI host in order to let the bridge
to probe: this recently started producing an endless -EPROBE_DEFER
loop on some machines that are using external bridges, like the
parade-ps8640, found on the ACER Chromebook R13.

Now that the DSI hosts/devices probe sequence is documented, we can
do adjustments to the mtk_dsi driver as to both fix now and make sure
to avoid this situation in the future: for this, following what is
documented in drm_bridge.c, move the mtk_dsi component_add() to the
mtk_dsi_ops.attach callback and delete it in the detach callback;
keeping in mind that we are registering a drm_bridge for our DSI,
which is only used/attached if the DSI Host is bound, it wouldn't
make sense to keep adding our bridge at probe time (as it would
be useless to have it if mtk_dsi_ops.attach() fails!), so also move
that one to the dsi host attach function (and remove it in detach).

Cc: <stable@vger.kernel.org> # 5.15.x
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
 1 file changed, 84 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 5d90d2eb0019..bced4c7d668e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
 	mtk_dsi_poweroff(dsi);
 }
 
+static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
+{
+	int ret;
+
+	ret = drm_simple_encoder_init(drm, &dsi->encoder,
+				      DRM_MODE_ENCODER_DSI);
+	if (ret) {
+		DRM_ERROR("Failed to encoder init to drm\n");
+		return ret;
+	}
+
+	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
+
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret)
+		goto err_cleanup_encoder;
+
+	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
+	if (IS_ERR(dsi->connector)) {
+		DRM_ERROR("Unable to create bridge connector\n");
+		ret = PTR_ERR(dsi->connector);
+		goto err_cleanup_encoder;
+	}
+	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
+
+	return 0;
+
+err_cleanup_encoder:
+	drm_encoder_cleanup(&dsi->encoder);
+	return ret;
+}
+
+static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	int ret;
+	struct drm_device *drm = data;
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	ret = mtk_dsi_encoder_init(drm, dsi);
+	if (ret)
+		return ret;
+
+	return device_reset_optional(dev);
+}
+
+static void mtk_dsi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	drm_encoder_cleanup(&dsi->encoder);
+}
+
+static const struct component_ops mtk_dsi_component_ops = {
+	.bind = mtk_dsi_bind,
+	.unbind = mtk_dsi_unbind,
+};
+
 static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
 			       struct mipi_dsi_device *device)
 {
 	struct mtk_dsi *dsi = host_to_dsi(host);
+	struct device *dev = host->dev;
+	int ret;
 
 	dsi->lanes = device->lanes;
 	dsi->format = device->format;
 	dsi->mode_flags = device->mode_flags;
+	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+	if (IS_ERR(dsi->next_bridge))
+		return PTR_ERR(dsi->next_bridge);
+
+	drm_bridge_add(&dsi->bridge);
+
+	ret = component_add(host->dev, &mtk_dsi_component_ops);
+	if (ret) {
+		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
+		drm_bridge_remove(&dsi->bridge);
+		return ret;
+	}
 
 	return 0;
 }
 
+static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
+			       struct mipi_dsi_device *device)
+{
+	struct mtk_dsi *dsi = host_to_dsi(host);
+
+	component_del(host->dev, &mtk_dsi_component_ops);
+	drm_bridge_remove(&dsi->bridge);
+	return 0;
+}
+
 static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
 {
 	int ret;
@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
 
 static const struct mipi_dsi_host_ops mtk_dsi_ops = {
 	.attach = mtk_dsi_host_attach,
+	.detach = mtk_dsi_host_detach,
 	.transfer = mtk_dsi_host_transfer,
 };
 
-static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
-{
-	int ret;
-
-	ret = drm_simple_encoder_init(drm, &dsi->encoder,
-				      DRM_MODE_ENCODER_DSI);
-	if (ret) {
-		DRM_ERROR("Failed to encoder init to drm\n");
-		return ret;
-	}
-
-	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
-
-	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
-				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
-	if (ret)
-		goto err_cleanup_encoder;
-
-	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
-	if (IS_ERR(dsi->connector)) {
-		DRM_ERROR("Unable to create bridge connector\n");
-		ret = PTR_ERR(dsi->connector);
-		goto err_cleanup_encoder;
-	}
-	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
-
-	return 0;
-
-err_cleanup_encoder:
-	drm_encoder_cleanup(&dsi->encoder);
-	return ret;
-}
-
-static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
-{
-	int ret;
-	struct drm_device *drm = data;
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	ret = mtk_dsi_encoder_init(drm, dsi);
-	if (ret)
-		return ret;
-
-	return device_reset_optional(dev);
-}
-
-static void mtk_dsi_unbind(struct device *dev, struct device *master,
-			   void *data)
-{
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	drm_encoder_cleanup(&dsi->encoder);
-}
-
-static const struct component_ops mtk_dsi_component_ops = {
-	.bind = mtk_dsi_bind,
-	.unbind = mtk_dsi_unbind,
-};
-
 static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct drm_panel *panel;
 	struct resource *regs;
 	int irq_num;
 	int ret;
@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-					  &panel, &dsi->next_bridge);
-	if (ret)
-		goto err_unregister_host;
-
-	if (panel) {
-		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
-		if (IS_ERR(dsi->next_bridge)) {
-			ret = PTR_ERR(dsi->next_bridge);
-			goto err_unregister_host;
-		}
-	}
-
 	dsi->driver_data = of_device_get_match_data(dev);
 
 	dsi->engine_clk = devm_clk_get(dev, "engine");
@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
-	drm_bridge_add(&dsi->bridge);
-
-	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
-		goto err_unregister_host;
-	}
-
 	return 0;
 
 err_unregister_host:
@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
 	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
 
 	mtk_output_dsi_disable(dsi);
-	drm_bridge_remove(&dsi->bridge);
-	component_del(&pdev->dev, &mtk_dsi_component_ops);
 	mipi_dsi_host_unregister(&dsi->host);
 
 	return 0;
-- 
2.33.1


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

* [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-01-31  8:55 ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-01-31  8:55 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-mediatek, linux-arm-kernel, linux-kernel, chunkuang.hu,
	p.zabel, airlied, daniel, matthias.bgg, kernel, andrzej.hajda,
	AngeloGioacchino Del Regno, stable, Jagan Teki

DRM bridge drivers are now attaching their DSI device at probe time,
which requires us to register our DSI host in order to let the bridge
to probe: this recently started producing an endless -EPROBE_DEFER
loop on some machines that are using external bridges, like the
parade-ps8640, found on the ACER Chromebook R13.

Now that the DSI hosts/devices probe sequence is documented, we can
do adjustments to the mtk_dsi driver as to both fix now and make sure
to avoid this situation in the future: for this, following what is
documented in drm_bridge.c, move the mtk_dsi component_add() to the
mtk_dsi_ops.attach callback and delete it in the detach callback;
keeping in mind that we are registering a drm_bridge for our DSI,
which is only used/attached if the DSI Host is bound, it wouldn't
make sense to keep adding our bridge at probe time (as it would
be useless to have it if mtk_dsi_ops.attach() fails!), so also move
that one to the dsi host attach function (and remove it in detach).

Cc: <stable@vger.kernel.org> # 5.15.x
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
 1 file changed, 84 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 5d90d2eb0019..bced4c7d668e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
 	mtk_dsi_poweroff(dsi);
 }
 
+static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
+{
+	int ret;
+
+	ret = drm_simple_encoder_init(drm, &dsi->encoder,
+				      DRM_MODE_ENCODER_DSI);
+	if (ret) {
+		DRM_ERROR("Failed to encoder init to drm\n");
+		return ret;
+	}
+
+	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
+
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret)
+		goto err_cleanup_encoder;
+
+	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
+	if (IS_ERR(dsi->connector)) {
+		DRM_ERROR("Unable to create bridge connector\n");
+		ret = PTR_ERR(dsi->connector);
+		goto err_cleanup_encoder;
+	}
+	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
+
+	return 0;
+
+err_cleanup_encoder:
+	drm_encoder_cleanup(&dsi->encoder);
+	return ret;
+}
+
+static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	int ret;
+	struct drm_device *drm = data;
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	ret = mtk_dsi_encoder_init(drm, dsi);
+	if (ret)
+		return ret;
+
+	return device_reset_optional(dev);
+}
+
+static void mtk_dsi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	drm_encoder_cleanup(&dsi->encoder);
+}
+
+static const struct component_ops mtk_dsi_component_ops = {
+	.bind = mtk_dsi_bind,
+	.unbind = mtk_dsi_unbind,
+};
+
 static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
 			       struct mipi_dsi_device *device)
 {
 	struct mtk_dsi *dsi = host_to_dsi(host);
+	struct device *dev = host->dev;
+	int ret;
 
 	dsi->lanes = device->lanes;
 	dsi->format = device->format;
 	dsi->mode_flags = device->mode_flags;
+	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+	if (IS_ERR(dsi->next_bridge))
+		return PTR_ERR(dsi->next_bridge);
+
+	drm_bridge_add(&dsi->bridge);
+
+	ret = component_add(host->dev, &mtk_dsi_component_ops);
+	if (ret) {
+		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
+		drm_bridge_remove(&dsi->bridge);
+		return ret;
+	}
 
 	return 0;
 }
 
+static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
+			       struct mipi_dsi_device *device)
+{
+	struct mtk_dsi *dsi = host_to_dsi(host);
+
+	component_del(host->dev, &mtk_dsi_component_ops);
+	drm_bridge_remove(&dsi->bridge);
+	return 0;
+}
+
 static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
 {
 	int ret;
@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
 
 static const struct mipi_dsi_host_ops mtk_dsi_ops = {
 	.attach = mtk_dsi_host_attach,
+	.detach = mtk_dsi_host_detach,
 	.transfer = mtk_dsi_host_transfer,
 };
 
-static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
-{
-	int ret;
-
-	ret = drm_simple_encoder_init(drm, &dsi->encoder,
-				      DRM_MODE_ENCODER_DSI);
-	if (ret) {
-		DRM_ERROR("Failed to encoder init to drm\n");
-		return ret;
-	}
-
-	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
-
-	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
-				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
-	if (ret)
-		goto err_cleanup_encoder;
-
-	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
-	if (IS_ERR(dsi->connector)) {
-		DRM_ERROR("Unable to create bridge connector\n");
-		ret = PTR_ERR(dsi->connector);
-		goto err_cleanup_encoder;
-	}
-	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
-
-	return 0;
-
-err_cleanup_encoder:
-	drm_encoder_cleanup(&dsi->encoder);
-	return ret;
-}
-
-static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
-{
-	int ret;
-	struct drm_device *drm = data;
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	ret = mtk_dsi_encoder_init(drm, dsi);
-	if (ret)
-		return ret;
-
-	return device_reset_optional(dev);
-}
-
-static void mtk_dsi_unbind(struct device *dev, struct device *master,
-			   void *data)
-{
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	drm_encoder_cleanup(&dsi->encoder);
-}
-
-static const struct component_ops mtk_dsi_component_ops = {
-	.bind = mtk_dsi_bind,
-	.unbind = mtk_dsi_unbind,
-};
-
 static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct drm_panel *panel;
 	struct resource *regs;
 	int irq_num;
 	int ret;
@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-					  &panel, &dsi->next_bridge);
-	if (ret)
-		goto err_unregister_host;
-
-	if (panel) {
-		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
-		if (IS_ERR(dsi->next_bridge)) {
-			ret = PTR_ERR(dsi->next_bridge);
-			goto err_unregister_host;
-		}
-	}
-
 	dsi->driver_data = of_device_get_match_data(dev);
 
 	dsi->engine_clk = devm_clk_get(dev, "engine");
@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
-	drm_bridge_add(&dsi->bridge);
-
-	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
-		goto err_unregister_host;
-	}
-
 	return 0;
 
 err_unregister_host:
@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
 	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
 
 	mtk_output_dsi_disable(dsi);
-	drm_bridge_remove(&dsi->bridge);
-	component_del(&pdev->dev, &mtk_dsi_component_ops);
 	mipi_dsi_host_unregister(&dsi->host);
 
 	return 0;
-- 
2.33.1


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-01-31  8:55 ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-01-31  8:55 UTC (permalink / raw)
  To: dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel, AngeloGioacchino Del Regno

DRM bridge drivers are now attaching their DSI device at probe time,
which requires us to register our DSI host in order to let the bridge
to probe: this recently started producing an endless -EPROBE_DEFER
loop on some machines that are using external bridges, like the
parade-ps8640, found on the ACER Chromebook R13.

Now that the DSI hosts/devices probe sequence is documented, we can
do adjustments to the mtk_dsi driver as to both fix now and make sure
to avoid this situation in the future: for this, following what is
documented in drm_bridge.c, move the mtk_dsi component_add() to the
mtk_dsi_ops.attach callback and delete it in the detach callback;
keeping in mind that we are registering a drm_bridge for our DSI,
which is only used/attached if the DSI Host is bound, it wouldn't
make sense to keep adding our bridge at probe time (as it would
be useless to have it if mtk_dsi_ops.attach() fails!), so also move
that one to the dsi host attach function (and remove it in detach).

Cc: <stable@vger.kernel.org> # 5.15.x
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
 1 file changed, 84 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 5d90d2eb0019..bced4c7d668e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
 	mtk_dsi_poweroff(dsi);
 }
 
+static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
+{
+	int ret;
+
+	ret = drm_simple_encoder_init(drm, &dsi->encoder,
+				      DRM_MODE_ENCODER_DSI);
+	if (ret) {
+		DRM_ERROR("Failed to encoder init to drm\n");
+		return ret;
+	}
+
+	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
+
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret)
+		goto err_cleanup_encoder;
+
+	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
+	if (IS_ERR(dsi->connector)) {
+		DRM_ERROR("Unable to create bridge connector\n");
+		ret = PTR_ERR(dsi->connector);
+		goto err_cleanup_encoder;
+	}
+	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
+
+	return 0;
+
+err_cleanup_encoder:
+	drm_encoder_cleanup(&dsi->encoder);
+	return ret;
+}
+
+static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	int ret;
+	struct drm_device *drm = data;
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	ret = mtk_dsi_encoder_init(drm, dsi);
+	if (ret)
+		return ret;
+
+	return device_reset_optional(dev);
+}
+
+static void mtk_dsi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	drm_encoder_cleanup(&dsi->encoder);
+}
+
+static const struct component_ops mtk_dsi_component_ops = {
+	.bind = mtk_dsi_bind,
+	.unbind = mtk_dsi_unbind,
+};
+
 static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
 			       struct mipi_dsi_device *device)
 {
 	struct mtk_dsi *dsi = host_to_dsi(host);
+	struct device *dev = host->dev;
+	int ret;
 
 	dsi->lanes = device->lanes;
 	dsi->format = device->format;
 	dsi->mode_flags = device->mode_flags;
+	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+	if (IS_ERR(dsi->next_bridge))
+		return PTR_ERR(dsi->next_bridge);
+
+	drm_bridge_add(&dsi->bridge);
+
+	ret = component_add(host->dev, &mtk_dsi_component_ops);
+	if (ret) {
+		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
+		drm_bridge_remove(&dsi->bridge);
+		return ret;
+	}
 
 	return 0;
 }
 
+static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
+			       struct mipi_dsi_device *device)
+{
+	struct mtk_dsi *dsi = host_to_dsi(host);
+
+	component_del(host->dev, &mtk_dsi_component_ops);
+	drm_bridge_remove(&dsi->bridge);
+	return 0;
+}
+
 static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
 {
 	int ret;
@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
 
 static const struct mipi_dsi_host_ops mtk_dsi_ops = {
 	.attach = mtk_dsi_host_attach,
+	.detach = mtk_dsi_host_detach,
 	.transfer = mtk_dsi_host_transfer,
 };
 
-static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
-{
-	int ret;
-
-	ret = drm_simple_encoder_init(drm, &dsi->encoder,
-				      DRM_MODE_ENCODER_DSI);
-	if (ret) {
-		DRM_ERROR("Failed to encoder init to drm\n");
-		return ret;
-	}
-
-	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
-
-	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
-				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
-	if (ret)
-		goto err_cleanup_encoder;
-
-	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
-	if (IS_ERR(dsi->connector)) {
-		DRM_ERROR("Unable to create bridge connector\n");
-		ret = PTR_ERR(dsi->connector);
-		goto err_cleanup_encoder;
-	}
-	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
-
-	return 0;
-
-err_cleanup_encoder:
-	drm_encoder_cleanup(&dsi->encoder);
-	return ret;
-}
-
-static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
-{
-	int ret;
-	struct drm_device *drm = data;
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	ret = mtk_dsi_encoder_init(drm, dsi);
-	if (ret)
-		return ret;
-
-	return device_reset_optional(dev);
-}
-
-static void mtk_dsi_unbind(struct device *dev, struct device *master,
-			   void *data)
-{
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	drm_encoder_cleanup(&dsi->encoder);
-}
-
-static const struct component_ops mtk_dsi_component_ops = {
-	.bind = mtk_dsi_bind,
-	.unbind = mtk_dsi_unbind,
-};
-
 static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct drm_panel *panel;
 	struct resource *regs;
 	int irq_num;
 	int ret;
@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-					  &panel, &dsi->next_bridge);
-	if (ret)
-		goto err_unregister_host;
-
-	if (panel) {
-		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
-		if (IS_ERR(dsi->next_bridge)) {
-			ret = PTR_ERR(dsi->next_bridge);
-			goto err_unregister_host;
-		}
-	}
-
 	dsi->driver_data = of_device_get_match_data(dev);
 
 	dsi->engine_clk = devm_clk_get(dev, "engine");
@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
-	drm_bridge_add(&dsi->bridge);
-
-	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
-		goto err_unregister_host;
-	}
-
 	return 0;
 
 err_unregister_host:
@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
 	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
 
 	mtk_output_dsi_disable(dsi);
-	drm_bridge_remove(&dsi->bridge);
-	component_del(&pdev->dev, &mtk_dsi_component_ops);
 	mipi_dsi_host_unregister(&dsi->host);
 
 	return 0;
-- 
2.33.1


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

* [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-01-31  8:55 ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-01-31  8:55 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-mediatek, linux-arm-kernel, linux-kernel, chunkuang.hu,
	p.zabel, airlied, daniel, matthias.bgg, kernel, andrzej.hajda,
	AngeloGioacchino Del Regno, stable, Jagan Teki

DRM bridge drivers are now attaching their DSI device at probe time,
which requires us to register our DSI host in order to let the bridge
to probe: this recently started producing an endless -EPROBE_DEFER
loop on some machines that are using external bridges, like the
parade-ps8640, found on the ACER Chromebook R13.

Now that the DSI hosts/devices probe sequence is documented, we can
do adjustments to the mtk_dsi driver as to both fix now and make sure
to avoid this situation in the future: for this, following what is
documented in drm_bridge.c, move the mtk_dsi component_add() to the
mtk_dsi_ops.attach callback and delete it in the detach callback;
keeping in mind that we are registering a drm_bridge for our DSI,
which is only used/attached if the DSI Host is bound, it wouldn't
make sense to keep adding our bridge at probe time (as it would
be useless to have it if mtk_dsi_ops.attach() fails!), so also move
that one to the dsi host attach function (and remove it in detach).

Cc: <stable@vger.kernel.org> # 5.15.x
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
 1 file changed, 84 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 5d90d2eb0019..bced4c7d668e 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
 	mtk_dsi_poweroff(dsi);
 }
 
+static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
+{
+	int ret;
+
+	ret = drm_simple_encoder_init(drm, &dsi->encoder,
+				      DRM_MODE_ENCODER_DSI);
+	if (ret) {
+		DRM_ERROR("Failed to encoder init to drm\n");
+		return ret;
+	}
+
+	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
+
+	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+	if (ret)
+		goto err_cleanup_encoder;
+
+	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
+	if (IS_ERR(dsi->connector)) {
+		DRM_ERROR("Unable to create bridge connector\n");
+		ret = PTR_ERR(dsi->connector);
+		goto err_cleanup_encoder;
+	}
+	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
+
+	return 0;
+
+err_cleanup_encoder:
+	drm_encoder_cleanup(&dsi->encoder);
+	return ret;
+}
+
+static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	int ret;
+	struct drm_device *drm = data;
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	ret = mtk_dsi_encoder_init(drm, dsi);
+	if (ret)
+		return ret;
+
+	return device_reset_optional(dev);
+}
+
+static void mtk_dsi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	drm_encoder_cleanup(&dsi->encoder);
+}
+
+static const struct component_ops mtk_dsi_component_ops = {
+	.bind = mtk_dsi_bind,
+	.unbind = mtk_dsi_unbind,
+};
+
 static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
 			       struct mipi_dsi_device *device)
 {
 	struct mtk_dsi *dsi = host_to_dsi(host);
+	struct device *dev = host->dev;
+	int ret;
 
 	dsi->lanes = device->lanes;
 	dsi->format = device->format;
 	dsi->mode_flags = device->mode_flags;
+	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+	if (IS_ERR(dsi->next_bridge))
+		return PTR_ERR(dsi->next_bridge);
+
+	drm_bridge_add(&dsi->bridge);
+
+	ret = component_add(host->dev, &mtk_dsi_component_ops);
+	if (ret) {
+		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
+		drm_bridge_remove(&dsi->bridge);
+		return ret;
+	}
 
 	return 0;
 }
 
+static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
+			       struct mipi_dsi_device *device)
+{
+	struct mtk_dsi *dsi = host_to_dsi(host);
+
+	component_del(host->dev, &mtk_dsi_component_ops);
+	drm_bridge_remove(&dsi->bridge);
+	return 0;
+}
+
 static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
 {
 	int ret;
@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
 
 static const struct mipi_dsi_host_ops mtk_dsi_ops = {
 	.attach = mtk_dsi_host_attach,
+	.detach = mtk_dsi_host_detach,
 	.transfer = mtk_dsi_host_transfer,
 };
 
-static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
-{
-	int ret;
-
-	ret = drm_simple_encoder_init(drm, &dsi->encoder,
-				      DRM_MODE_ENCODER_DSI);
-	if (ret) {
-		DRM_ERROR("Failed to encoder init to drm\n");
-		return ret;
-	}
-
-	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
-
-	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
-				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
-	if (ret)
-		goto err_cleanup_encoder;
-
-	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
-	if (IS_ERR(dsi->connector)) {
-		DRM_ERROR("Unable to create bridge connector\n");
-		ret = PTR_ERR(dsi->connector);
-		goto err_cleanup_encoder;
-	}
-	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
-
-	return 0;
-
-err_cleanup_encoder:
-	drm_encoder_cleanup(&dsi->encoder);
-	return ret;
-}
-
-static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
-{
-	int ret;
-	struct drm_device *drm = data;
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	ret = mtk_dsi_encoder_init(drm, dsi);
-	if (ret)
-		return ret;
-
-	return device_reset_optional(dev);
-}
-
-static void mtk_dsi_unbind(struct device *dev, struct device *master,
-			   void *data)
-{
-	struct mtk_dsi *dsi = dev_get_drvdata(dev);
-
-	drm_encoder_cleanup(&dsi->encoder);
-}
-
-static const struct component_ops mtk_dsi_component_ops = {
-	.bind = mtk_dsi_bind,
-	.unbind = mtk_dsi_unbind,
-};
-
 static int mtk_dsi_probe(struct platform_device *pdev)
 {
 	struct mtk_dsi *dsi;
 	struct device *dev = &pdev->dev;
-	struct drm_panel *panel;
 	struct resource *regs;
 	int irq_num;
 	int ret;
@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
-					  &panel, &dsi->next_bridge);
-	if (ret)
-		goto err_unregister_host;
-
-	if (panel) {
-		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
-		if (IS_ERR(dsi->next_bridge)) {
-			ret = PTR_ERR(dsi->next_bridge);
-			goto err_unregister_host;
-		}
-	}
-
 	dsi->driver_data = of_device_get_match_data(dev);
 
 	dsi->engine_clk = devm_clk_get(dev, "engine");
@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->bridge.of_node = dev->of_node;
 	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
 
-	drm_bridge_add(&dsi->bridge);
-
-	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
-		goto err_unregister_host;
-	}
-
 	return 0;
 
 err_unregister_host:
@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
 	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
 
 	mtk_output_dsi_disable(dsi);
-	drm_bridge_remove(&dsi->bridge);
-	component_del(&pdev->dev, &mtk_dsi_component_ops);
 	mipi_dsi_host_unregister(&dsi->host);
 
 	return 0;
-- 
2.33.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
  2022-01-31  8:55 ` AngeloGioacchino Del Regno
  (?)
  (?)
@ 2022-02-08  8:20   ` CK Hu
  -1 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:20 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, linux-mediatek,
	Jagan Teki, andrzej.hajda, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> ----
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> 

[snip]

> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> 0);

The original would process panel. Why do you remove the panel part?
It's better that someone has a platform of DSI->Panel to test this
patch.

Regards,
CK

> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n",
> ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> 

[snip]

> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n",
> ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;


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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  8:20   ` CK Hu
  0 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:20 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> ----
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> 

[snip]

> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> 0);

The original would process panel. Why do you remove the panel part?
It's better that someone has a platform of DSI->Panel to test this
patch.

Regards,
CK

> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n",
> ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> 

[snip]

> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n",
> ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;


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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  8:20   ` CK Hu
  0 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:20 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> ----
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> 

[snip]

> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> 0);

The original would process panel. Why do you remove the panel part?
It's better that someone has a platform of DSI->Panel to test this
patch.

Regards,
CK

> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n",
> ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> 

[snip]

> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n",
> ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  8:20   ` CK Hu
  0 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:20 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <
> angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> ----
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> 

[snip]

> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> 0);

The original would process panel. Why do you remove the panel part?
It's better that someone has a platform of DSI->Panel to test this
patch.

Regards,
CK

> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n",
> ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> 

[snip]

> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n",
> ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
  2022-02-08  8:20   ` CK Hu
  (?)
  (?)
@ 2022-02-08  8:32     ` CK Hu
  -1 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:32 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
> Hi, Angelo:
> 
> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> > DRM bridge drivers are now attaching their DSI device at probe
> > time,
> > which requires us to register our DSI host in order to let the
> > bridge
> > to probe: this recently started producing an endless -EPROBE_DEFER
> > loop on some machines that are using external bridges, like the
> > parade-ps8640, found on the ACER Chromebook R13.
> > 
> > Now that the DSI hosts/devices probe sequence is documented, we can
> > do adjustments to the mtk_dsi driver as to both fix now and make
> > sure
> > to avoid this situation in the future: for this, following what is
> > documented in drm_bridge.c, move the mtk_dsi component_add() to the
> > mtk_dsi_ops.attach callback and delete it in the detach callback;
> > keeping in mind that we are registering a drm_bridge for our DSI,
> > which is only used/attached if the DSI Host is bound, it wouldn't
> > make sense to keep adding our bridge at probe time (as it would
> > be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> > that one to the dsi host attach function (and remove it in detach).
> > 
> > Cc: <stable@vger.kernel.org> # 5.15.x
> > Signed-off-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@collabora.com>
> > Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> > Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> > 
> > ---
> >  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> > ----
> >  1 file changed, 84 insertions(+), 83 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > index 5d90d2eb0019..bced4c7d668e 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
> >  	mtk_dsi_poweroff(dsi);
> >  }
> >  
> > 
> 
> [snip]
> 
> > +
> >  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
> >  			       struct mipi_dsi_device *device)
> >  {
> >  	struct mtk_dsi *dsi = host_to_dsi(host);
> > +	struct device *dev = host->dev;
> > +	int ret;
> >  
> >  	dsi->lanes = device->lanes;
> >  	dsi->format = device->format;
> >  	dsi->mode_flags = device->mode_flags;
> > +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> > 0);
> 
> The original would process panel. Why do you remove the panel part?
> It's better that someone has a platform of DSI->Panel to test this
> patch.

Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
this patch,

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> 
> Regards,
> CK
> 
> > +	if (IS_ERR(dsi->next_bridge))
> > +		return PTR_ERR(dsi->next_bridge);
> > +
> > +	drm_bridge_add(&dsi->bridge);
> > +
> > +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> > +	if (ret) {
> > +		DRM_ERROR("failed to add dsi_host component: %d\n",
> > ret);
> > +		drm_bridge_remove(&dsi->bridge);
> > +		return ret;
> > +	}
> >  
> >  	return 0;
> >  }
> >  
> > +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> > +			       struct mipi_dsi_device *device)
> > +{
> > +	struct mtk_dsi *dsi = host_to_dsi(host);
> > +
> > +	component_del(host->dev, &mtk_dsi_component_ops);
> > +	drm_bridge_remove(&dsi->bridge);
> > +	return 0;
> > +}
> > +
> >  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> >  {
> >  	int ret;
> > @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> > mipi_dsi_host *host,
> >  
> >  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
> >  	.attach = mtk_dsi_host_attach,
> > +	.detach = mtk_dsi_host_detach,
> >  	.transfer = mtk_dsi_host_transfer,
> >  };
> >  
> > 
> 
> [snip]
> 
> > -
> >  static int mtk_dsi_probe(struct platform_device *pdev)
> >  {
> >  	struct mtk_dsi *dsi;
> >  	struct device *dev = &pdev->dev;
> > -	struct drm_panel *panel;
> >  	struct resource *regs;
> >  	int irq_num;
> >  	int ret;
> > @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  		return ret;
> >  	}
> >  
> > -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> > -					  &panel, &dsi->next_bridge);
> > -	if (ret)
> > -		goto err_unregister_host;
> > -
> > -	if (panel) {
> > -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> > panel);
> > -		if (IS_ERR(dsi->next_bridge)) {
> > -			ret = PTR_ERR(dsi->next_bridge);
> > -			goto err_unregister_host;
> > -		}
> > -	}
> > -
> >  	dsi->driver_data = of_device_get_match_data(dev);
> >  
> >  	dsi->engine_clk = devm_clk_get(dev, "engine");
> > @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  	dsi->bridge.of_node = dev->of_node;
> >  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> >  
> > -	drm_bridge_add(&dsi->bridge);
> > -
> > -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> > -	if (ret) {
> > -		dev_err(&pdev->dev, "failed to add component: %d\n",
> > ret);
> > -		goto err_unregister_host;
> > -	}
> > -
> >  	return 0;
> >  
> >  err_unregister_host:
> > @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> > platform_device *pdev)
> >  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
> >  
> >  	mtk_output_dsi_disable(dsi);
> > -	drm_bridge_remove(&dsi->bridge);
> > -	component_del(&pdev->dev, &mtk_dsi_component_ops);
> >  	mipi_dsi_host_unregister(&dsi->host);
> >  
> >  	return 0;


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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  8:32     ` CK Hu
  0 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:32 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
> Hi, Angelo:
> 
> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> > DRM bridge drivers are now attaching their DSI device at probe
> > time,
> > which requires us to register our DSI host in order to let the
> > bridge
> > to probe: this recently started producing an endless -EPROBE_DEFER
> > loop on some machines that are using external bridges, like the
> > parade-ps8640, found on the ACER Chromebook R13.
> > 
> > Now that the DSI hosts/devices probe sequence is documented, we can
> > do adjustments to the mtk_dsi driver as to both fix now and make
> > sure
> > to avoid this situation in the future: for this, following what is
> > documented in drm_bridge.c, move the mtk_dsi component_add() to the
> > mtk_dsi_ops.attach callback and delete it in the detach callback;
> > keeping in mind that we are registering a drm_bridge for our DSI,
> > which is only used/attached if the DSI Host is bound, it wouldn't
> > make sense to keep adding our bridge at probe time (as it would
> > be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> > that one to the dsi host attach function (and remove it in detach).
> > 
> > Cc: <stable@vger.kernel.org> # 5.15.x
> > Signed-off-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@collabora.com>
> > Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> > Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> > 
> > ---
> >  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> > ----
> >  1 file changed, 84 insertions(+), 83 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > index 5d90d2eb0019..bced4c7d668e 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
> >  	mtk_dsi_poweroff(dsi);
> >  }
> >  
> > 
> 
> [snip]
> 
> > +
> >  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
> >  			       struct mipi_dsi_device *device)
> >  {
> >  	struct mtk_dsi *dsi = host_to_dsi(host);
> > +	struct device *dev = host->dev;
> > +	int ret;
> >  
> >  	dsi->lanes = device->lanes;
> >  	dsi->format = device->format;
> >  	dsi->mode_flags = device->mode_flags;
> > +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> > 0);
> 
> The original would process panel. Why do you remove the panel part?
> It's better that someone has a platform of DSI->Panel to test this
> patch.

Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
this patch,

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> 
> Regards,
> CK
> 
> > +	if (IS_ERR(dsi->next_bridge))
> > +		return PTR_ERR(dsi->next_bridge);
> > +
> > +	drm_bridge_add(&dsi->bridge);
> > +
> > +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> > +	if (ret) {
> > +		DRM_ERROR("failed to add dsi_host component: %d\n",
> > ret);
> > +		drm_bridge_remove(&dsi->bridge);
> > +		return ret;
> > +	}
> >  
> >  	return 0;
> >  }
> >  
> > +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> > +			       struct mipi_dsi_device *device)
> > +{
> > +	struct mtk_dsi *dsi = host_to_dsi(host);
> > +
> > +	component_del(host->dev, &mtk_dsi_component_ops);
> > +	drm_bridge_remove(&dsi->bridge);
> > +	return 0;
> > +}
> > +
> >  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> >  {
> >  	int ret;
> > @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> > mipi_dsi_host *host,
> >  
> >  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
> >  	.attach = mtk_dsi_host_attach,
> > +	.detach = mtk_dsi_host_detach,
> >  	.transfer = mtk_dsi_host_transfer,
> >  };
> >  
> > 
> 
> [snip]
> 
> > -
> >  static int mtk_dsi_probe(struct platform_device *pdev)
> >  {
> >  	struct mtk_dsi *dsi;
> >  	struct device *dev = &pdev->dev;
> > -	struct drm_panel *panel;
> >  	struct resource *regs;
> >  	int irq_num;
> >  	int ret;
> > @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  		return ret;
> >  	}
> >  
> > -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> > -					  &panel, &dsi->next_bridge);
> > -	if (ret)
> > -		goto err_unregister_host;
> > -
> > -	if (panel) {
> > -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> > panel);
> > -		if (IS_ERR(dsi->next_bridge)) {
> > -			ret = PTR_ERR(dsi->next_bridge);
> > -			goto err_unregister_host;
> > -		}
> > -	}
> > -
> >  	dsi->driver_data = of_device_get_match_data(dev);
> >  
> >  	dsi->engine_clk = devm_clk_get(dev, "engine");
> > @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  	dsi->bridge.of_node = dev->of_node;
> >  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> >  
> > -	drm_bridge_add(&dsi->bridge);
> > -
> > -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> > -	if (ret) {
> > -		dev_err(&pdev->dev, "failed to add component: %d\n",
> > ret);
> > -		goto err_unregister_host;
> > -	}
> > -
> >  	return 0;
> >  
> >  err_unregister_host:
> > @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> > platform_device *pdev)
> >  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
> >  
> >  	mtk_output_dsi_disable(dsi);
> > -	drm_bridge_remove(&dsi->bridge);
> > -	component_del(&pdev->dev, &mtk_dsi_component_ops);
> >  	mipi_dsi_host_unregister(&dsi->host);
> >  
> >  	return 0;


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  8:32     ` CK Hu
  0 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:32 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, linux-mediatek,
	Jagan Teki, andrzej.hajda, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
> Hi, Angelo:
> 
> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> > DRM bridge drivers are now attaching their DSI device at probe
> > time,
> > which requires us to register our DSI host in order to let the
> > bridge
> > to probe: this recently started producing an endless -EPROBE_DEFER
> > loop on some machines that are using external bridges, like the
> > parade-ps8640, found on the ACER Chromebook R13.
> > 
> > Now that the DSI hosts/devices probe sequence is documented, we can
> > do adjustments to the mtk_dsi driver as to both fix now and make
> > sure
> > to avoid this situation in the future: for this, following what is
> > documented in drm_bridge.c, move the mtk_dsi component_add() to the
> > mtk_dsi_ops.attach callback and delete it in the detach callback;
> > keeping in mind that we are registering a drm_bridge for our DSI,
> > which is only used/attached if the DSI Host is bound, it wouldn't
> > make sense to keep adding our bridge at probe time (as it would
> > be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> > that one to the dsi host attach function (and remove it in detach).
> > 
> > Cc: <stable@vger.kernel.org> # 5.15.x
> > Signed-off-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@collabora.com>
> > Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> > Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> > 
> > ---
> >  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> > ----
> >  1 file changed, 84 insertions(+), 83 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > index 5d90d2eb0019..bced4c7d668e 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
> >  	mtk_dsi_poweroff(dsi);
> >  }
> >  
> > 
> 
> [snip]
> 
> > +
> >  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
> >  			       struct mipi_dsi_device *device)
> >  {
> >  	struct mtk_dsi *dsi = host_to_dsi(host);
> > +	struct device *dev = host->dev;
> > +	int ret;
> >  
> >  	dsi->lanes = device->lanes;
> >  	dsi->format = device->format;
> >  	dsi->mode_flags = device->mode_flags;
> > +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> > 0);
> 
> The original would process panel. Why do you remove the panel part?
> It's better that someone has a platform of DSI->Panel to test this
> patch.

Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
this patch,

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> 
> Regards,
> CK
> 
> > +	if (IS_ERR(dsi->next_bridge))
> > +		return PTR_ERR(dsi->next_bridge);
> > +
> > +	drm_bridge_add(&dsi->bridge);
> > +
> > +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> > +	if (ret) {
> > +		DRM_ERROR("failed to add dsi_host component: %d\n",
> > ret);
> > +		drm_bridge_remove(&dsi->bridge);
> > +		return ret;
> > +	}
> >  
> >  	return 0;
> >  }
> >  
> > +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> > +			       struct mipi_dsi_device *device)
> > +{
> > +	struct mtk_dsi *dsi = host_to_dsi(host);
> > +
> > +	component_del(host->dev, &mtk_dsi_component_ops);
> > +	drm_bridge_remove(&dsi->bridge);
> > +	return 0;
> > +}
> > +
> >  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> >  {
> >  	int ret;
> > @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> > mipi_dsi_host *host,
> >  
> >  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
> >  	.attach = mtk_dsi_host_attach,
> > +	.detach = mtk_dsi_host_detach,
> >  	.transfer = mtk_dsi_host_transfer,
> >  };
> >  
> > 
> 
> [snip]
> 
> > -
> >  static int mtk_dsi_probe(struct platform_device *pdev)
> >  {
> >  	struct mtk_dsi *dsi;
> >  	struct device *dev = &pdev->dev;
> > -	struct drm_panel *panel;
> >  	struct resource *regs;
> >  	int irq_num;
> >  	int ret;
> > @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  		return ret;
> >  	}
> >  
> > -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> > -					  &panel, &dsi->next_bridge);
> > -	if (ret)
> > -		goto err_unregister_host;
> > -
> > -	if (panel) {
> > -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> > panel);
> > -		if (IS_ERR(dsi->next_bridge)) {
> > -			ret = PTR_ERR(dsi->next_bridge);
> > -			goto err_unregister_host;
> > -		}
> > -	}
> > -
> >  	dsi->driver_data = of_device_get_match_data(dev);
> >  
> >  	dsi->engine_clk = devm_clk_get(dev, "engine");
> > @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  	dsi->bridge.of_node = dev->of_node;
> >  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> >  
> > -	drm_bridge_add(&dsi->bridge);
> > -
> > -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> > -	if (ret) {
> > -		dev_err(&pdev->dev, "failed to add component: %d\n",
> > ret);
> > -		goto err_unregister_host;
> > -	}
> > -
> >  	return 0;
> >  
> >  err_unregister_host:
> > @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> > platform_device *pdev)
> >  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
> >  
> >  	mtk_output_dsi_disable(dsi);
> > -	drm_bridge_remove(&dsi->bridge);
> > -	component_del(&pdev->dev, &mtk_dsi_component_ops);
> >  	mipi_dsi_host_unregister(&dsi->host);
> >  
> >  	return 0;


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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  8:32     ` CK Hu
  0 siblings, 0 replies; 24+ messages in thread
From: CK Hu @ 2022-02-08  8:32 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Hi, Angelo:

On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
> Hi, Angelo:
> 
> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
> > DRM bridge drivers are now attaching their DSI device at probe
> > time,
> > which requires us to register our DSI host in order to let the
> > bridge
> > to probe: this recently started producing an endless -EPROBE_DEFER
> > loop on some machines that are using external bridges, like the
> > parade-ps8640, found on the ACER Chromebook R13.
> > 
> > Now that the DSI hosts/devices probe sequence is documented, we can
> > do adjustments to the mtk_dsi driver as to both fix now and make
> > sure
> > to avoid this situation in the future: for this, following what is
> > documented in drm_bridge.c, move the mtk_dsi component_add() to the
> > mtk_dsi_ops.attach callback and delete it in the detach callback;
> > keeping in mind that we are registering a drm_bridge for our DSI,
> > which is only used/attached if the DSI Host is bound, it wouldn't
> > make sense to keep adding our bridge at probe time (as it would
> > be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> > that one to the dsi host attach function (and remove it in detach).
> > 
> > Cc: <stable@vger.kernel.org> # 5.15.x
> > Signed-off-by: AngeloGioacchino Del Regno <
> > angelogioacchino.delregno@collabora.com>
> > Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> > Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
> > 
> > ---
> >  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
> > ----
> >  1 file changed, 84 insertions(+), 83 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > index 5d90d2eb0019..bced4c7d668e 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
> >  	mtk_dsi_poweroff(dsi);
> >  }
> >  
> > 
> 
> [snip]
> 
> > +
> >  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
> >  			       struct mipi_dsi_device *device)
> >  {
> >  	struct mtk_dsi *dsi = host_to_dsi(host);
> > +	struct device *dev = host->dev;
> > +	int ret;
> >  
> >  	dsi->lanes = device->lanes;
> >  	dsi->format = device->format;
> >  	dsi->mode_flags = device->mode_flags;
> > +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
> > 0);
> 
> The original would process panel. Why do you remove the panel part?
> It's better that someone has a platform of DSI->Panel to test this
> patch.

Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
this patch,

Reviewed-by: CK Hu <ck.hu@mediatek.com>

> 
> Regards,
> CK
> 
> > +	if (IS_ERR(dsi->next_bridge))
> > +		return PTR_ERR(dsi->next_bridge);
> > +
> > +	drm_bridge_add(&dsi->bridge);
> > +
> > +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> > +	if (ret) {
> > +		DRM_ERROR("failed to add dsi_host component: %d\n",
> > ret);
> > +		drm_bridge_remove(&dsi->bridge);
> > +		return ret;
> > +	}
> >  
> >  	return 0;
> >  }
> >  
> > +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> > +			       struct mipi_dsi_device *device)
> > +{
> > +	struct mtk_dsi *dsi = host_to_dsi(host);
> > +
> > +	component_del(host->dev, &mtk_dsi_component_ops);
> > +	drm_bridge_remove(&dsi->bridge);
> > +	return 0;
> > +}
> > +
> >  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> >  {
> >  	int ret;
> > @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct
> > mipi_dsi_host *host,
> >  
> >  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
> >  	.attach = mtk_dsi_host_attach,
> > +	.detach = mtk_dsi_host_detach,
> >  	.transfer = mtk_dsi_host_transfer,
> >  };
> >  
> > 
> 
> [snip]
> 
> > -
> >  static int mtk_dsi_probe(struct platform_device *pdev)
> >  {
> >  	struct mtk_dsi *dsi;
> >  	struct device *dev = &pdev->dev;
> > -	struct drm_panel *panel;
> >  	struct resource *regs;
> >  	int irq_num;
> >  	int ret;
> > @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  		return ret;
> >  	}
> >  
> > -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> > -					  &panel, &dsi->next_bridge);
> > -	if (ret)
> > -		goto err_unregister_host;
> > -
> > -	if (panel) {
> > -		dsi->next_bridge = devm_drm_panel_bridge_add(dev,
> > panel);
> > -		if (IS_ERR(dsi->next_bridge)) {
> > -			ret = PTR_ERR(dsi->next_bridge);
> > -			goto err_unregister_host;
> > -		}
> > -	}
> > -
> >  	dsi->driver_data = of_device_get_match_data(dev);
> >  
> >  	dsi->engine_clk = devm_clk_get(dev, "engine");
> > @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct
> > platform_device *pdev)
> >  	dsi->bridge.of_node = dev->of_node;
> >  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> >  
> > -	drm_bridge_add(&dsi->bridge);
> > -
> > -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> > -	if (ret) {
> > -		dev_err(&pdev->dev, "failed to add component: %d\n",
> > ret);
> > -		goto err_unregister_host;
> > -	}
> > -
> >  	return 0;
> >  
> >  err_unregister_host:
> > @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct
> > platform_device *pdev)
> >  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
> >  
> >  	mtk_output_dsi_disable(dsi);
> > -	drm_bridge_remove(&dsi->bridge);
> > -	component_del(&pdev->dev, &mtk_dsi_component_ops);
> >  	mipi_dsi_host_unregister(&dsi->host);
> >  
> >  	return 0;


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
  2022-02-08  8:32     ` CK Hu
  (?)
  (?)
@ 2022-02-08  9:03       ` AngeloGioacchino Del Regno
  -1 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-08  9:03 UTC (permalink / raw)
  To: CK Hu, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, linux-mediatek,
	Jagan Teki, andrzej.hajda, matthias.bgg, kernel,
	linux-arm-kernel

Il 08/02/22 09:32, CK Hu ha scritto:
> Hi, Angelo:
> 
> On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
>> Hi, Angelo:
>>
>> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
>>> DRM bridge drivers are now attaching their DSI device at probe
>>> time,
>>> which requires us to register our DSI host in order to let the
>>> bridge
>>> to probe: this recently started producing an endless -EPROBE_DEFER
>>> loop on some machines that are using external bridges, like the
>>> parade-ps8640, found on the ACER Chromebook R13.
>>>
>>> Now that the DSI hosts/devices probe sequence is documented, we can
>>> do adjustments to the mtk_dsi driver as to both fix now and make
>>> sure
>>> to avoid this situation in the future: for this, following what is
>>> documented in drm_bridge.c, move the mtk_dsi component_add() to the
>>> mtk_dsi_ops.attach callback and delete it in the detach callback;
>>> keeping in mind that we are registering a drm_bridge for our DSI,
>>> which is only used/attached if the DSI Host is bound, it wouldn't
>>> make sense to keep adding our bridge at probe time (as it would
>>> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
>>> that one to the dsi host attach function (and remove it in detach).
>>>
>>> Cc: <stable@vger.kernel.org> # 5.15.x
>>> Signed-off-by: AngeloGioacchino Del Regno <
>>> angelogioacchino.delregno@collabora.com>
>>> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
>>> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>>>
>>> ---
>>>   drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
>>> ----
>>>   1 file changed, 84 insertions(+), 83 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> index 5d90d2eb0019..bced4c7d668e 100644
>>> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>>>   	mtk_dsi_poweroff(dsi);
>>>   }
>>>   
>>>
>>
>> [snip]
>>
>>> +
>>>   static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>>>   			       struct mipi_dsi_device *device)
>>>   {
>>>   	struct mtk_dsi *dsi = host_to_dsi(host);
>>> +	struct device *dev = host->dev;
>>> +	int ret;
>>>   
>>>   	dsi->lanes = device->lanes;
>>>   	dsi->format = device->format;
>>>   	dsi->mode_flags = device->mode_flags;
>>> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
>>> 0);
>>
>> The original would process panel. Why do you remove the panel part?
>> It's better that someone has a platform of DSI->Panel to test this
>> patch.
> 
> Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
> this patch,
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 

No worries! Thanks for the review/approval.

Regards,
Angelo

>>
>> Regards,
>> CK
>>

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  9:03       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-08  9:03 UTC (permalink / raw)
  To: CK Hu, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Il 08/02/22 09:32, CK Hu ha scritto:
> Hi, Angelo:
> 
> On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
>> Hi, Angelo:
>>
>> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
>>> DRM bridge drivers are now attaching their DSI device at probe
>>> time,
>>> which requires us to register our DSI host in order to let the
>>> bridge
>>> to probe: this recently started producing an endless -EPROBE_DEFER
>>> loop on some machines that are using external bridges, like the
>>> parade-ps8640, found on the ACER Chromebook R13.
>>>
>>> Now that the DSI hosts/devices probe sequence is documented, we can
>>> do adjustments to the mtk_dsi driver as to both fix now and make
>>> sure
>>> to avoid this situation in the future: for this, following what is
>>> documented in drm_bridge.c, move the mtk_dsi component_add() to the
>>> mtk_dsi_ops.attach callback and delete it in the detach callback;
>>> keeping in mind that we are registering a drm_bridge for our DSI,
>>> which is only used/attached if the DSI Host is bound, it wouldn't
>>> make sense to keep adding our bridge at probe time (as it would
>>> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
>>> that one to the dsi host attach function (and remove it in detach).
>>>
>>> Cc: <stable@vger.kernel.org> # 5.15.x
>>> Signed-off-by: AngeloGioacchino Del Regno <
>>> angelogioacchino.delregno@collabora.com>
>>> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
>>> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>>>
>>> ---
>>>   drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
>>> ----
>>>   1 file changed, 84 insertions(+), 83 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> index 5d90d2eb0019..bced4c7d668e 100644
>>> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>>>   	mtk_dsi_poweroff(dsi);
>>>   }
>>>   
>>>
>>
>> [snip]
>>
>>> +
>>>   static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>>>   			       struct mipi_dsi_device *device)
>>>   {
>>>   	struct mtk_dsi *dsi = host_to_dsi(host);
>>> +	struct device *dev = host->dev;
>>> +	int ret;
>>>   
>>>   	dsi->lanes = device->lanes;
>>>   	dsi->format = device->format;
>>>   	dsi->mode_flags = device->mode_flags;
>>> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
>>> 0);
>>
>> The original would process panel. Why do you remove the panel part?
>> It's better that someone has a platform of DSI->Panel to test this
>> patch.
> 
> Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
> this patch,
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 

No worries! Thanks for the review/approval.

Regards,
Angelo

>>
>> Regards,
>> CK
>>

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  9:03       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-08  9:03 UTC (permalink / raw)
  To: CK Hu, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Il 08/02/22 09:32, CK Hu ha scritto:
> Hi, Angelo:
> 
> On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
>> Hi, Angelo:
>>
>> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
>>> DRM bridge drivers are now attaching their DSI device at probe
>>> time,
>>> which requires us to register our DSI host in order to let the
>>> bridge
>>> to probe: this recently started producing an endless -EPROBE_DEFER
>>> loop on some machines that are using external bridges, like the
>>> parade-ps8640, found on the ACER Chromebook R13.
>>>
>>> Now that the DSI hosts/devices probe sequence is documented, we can
>>> do adjustments to the mtk_dsi driver as to both fix now and make
>>> sure
>>> to avoid this situation in the future: for this, following what is
>>> documented in drm_bridge.c, move the mtk_dsi component_add() to the
>>> mtk_dsi_ops.attach callback and delete it in the detach callback;
>>> keeping in mind that we are registering a drm_bridge for our DSI,
>>> which is only used/attached if the DSI Host is bound, it wouldn't
>>> make sense to keep adding our bridge at probe time (as it would
>>> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
>>> that one to the dsi host attach function (and remove it in detach).
>>>
>>> Cc: <stable@vger.kernel.org> # 5.15.x
>>> Signed-off-by: AngeloGioacchino Del Regno <
>>> angelogioacchino.delregno@collabora.com>
>>> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
>>> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>>>
>>> ---
>>>   drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
>>> ----
>>>   1 file changed, 84 insertions(+), 83 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> index 5d90d2eb0019..bced4c7d668e 100644
>>> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>>>   	mtk_dsi_poweroff(dsi);
>>>   }
>>>   
>>>
>>
>> [snip]
>>
>>> +
>>>   static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>>>   			       struct mipi_dsi_device *device)
>>>   {
>>>   	struct mtk_dsi *dsi = host_to_dsi(host);
>>> +	struct device *dev = host->dev;
>>> +	int ret;
>>>   
>>>   	dsi->lanes = device->lanes;
>>>   	dsi->format = device->format;
>>>   	dsi->mode_flags = device->mode_flags;
>>> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
>>> 0);
>>
>> The original would process panel. Why do you remove the panel part?
>> It's better that someone has a platform of DSI->Panel to test this
>> patch.
> 
> Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
> this patch,
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 

No worries! Thanks for the review/approval.

Regards,
Angelo

>>
>> Regards,
>> CK
>>

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-08  9:03       ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 24+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-02-08  9:03 UTC (permalink / raw)
  To: CK Hu, dri-devel
  Cc: chunkuang.hu, airlied, linux-kernel, stable, andrzej.hajda,
	linux-mediatek, Jagan Teki, matthias.bgg, kernel,
	linux-arm-kernel

Il 08/02/22 09:32, CK Hu ha scritto:
> Hi, Angelo:
> 
> On Tue, 2022-02-08 at 16:20 +0800, CK Hu wrote:
>> Hi, Angelo:
>>
>> On Mon, 2022-01-31 at 09:55 +0100, AngeloGioacchino Del Regno wrote:
>>> DRM bridge drivers are now attaching their DSI device at probe
>>> time,
>>> which requires us to register our DSI host in order to let the
>>> bridge
>>> to probe: this recently started producing an endless -EPROBE_DEFER
>>> loop on some machines that are using external bridges, like the
>>> parade-ps8640, found on the ACER Chromebook R13.
>>>
>>> Now that the DSI hosts/devices probe sequence is documented, we can
>>> do adjustments to the mtk_dsi driver as to both fix now and make
>>> sure
>>> to avoid this situation in the future: for this, following what is
>>> documented in drm_bridge.c, move the mtk_dsi component_add() to the
>>> mtk_dsi_ops.attach callback and delete it in the detach callback;
>>> keeping in mind that we are registering a drm_bridge for our DSI,
>>> which is only used/attached if the DSI Host is bound, it wouldn't
>>> make sense to keep adding our bridge at probe time (as it would
>>> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
>>> that one to the dsi host attach function (and remove it in detach).
>>>
>>> Cc: <stable@vger.kernel.org> # 5.15.x
>>> Signed-off-by: AngeloGioacchino Del Regno <
>>> angelogioacchino.delregno@collabora.com>
>>> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
>>> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>>>
>>> ---
>>>   drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++----------
>>> ----
>>>   1 file changed, 84 insertions(+), 83 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> index 5d90d2eb0019..bced4c7d668e 100644
>>> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
>>> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>>>   	mtk_dsi_poweroff(dsi);
>>>   }
>>>   
>>>
>>
>> [snip]
>>
>>> +
>>>   static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>>>   			       struct mipi_dsi_device *device)
>>>   {
>>>   	struct mtk_dsi *dsi = host_to_dsi(host);
>>> +	struct device *dev = host->dev;
>>> +	int ret;
>>>   
>>>   	dsi->lanes = device->lanes;
>>>   	dsi->format = device->format;
>>>   	dsi->mode_flags = device->mode_flags;
>>> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0,
>>> 0);
>>
>> The original would process panel. Why do you remove the panel part?
>> It's better that someone has a platform of DSI->Panel to test this
>> patch.
> 
> Sorry, devm_drm_of_get_bridge() has processed the panel part, so for
> this patch,
> 
> Reviewed-by: CK Hu <ck.hu@mediatek.com>
> 

No worries! Thanks for the review/approval.

Regards,
Angelo

>>
>> Regards,
>> CK
>>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
  2022-01-31  8:55 ` AngeloGioacchino Del Regno
  (?)
  (?)
@ 2022-02-09 14:48   ` Nícolas F. R. A. Prado
  -1 siblings, 0 replies; 24+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-02-09 14:48 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	chunkuang.hu, p.zabel, airlied, daniel, matthias.bgg, kernel,
	andrzej.hajda, stable, Jagan Teki

Hi Angelo,

On Mon, Jan 31, 2022 at 09:55:20AM +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

Thanks,
Nícolas

> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +	int ret;
> +
> +	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +				      DRM_MODE_ENCODER_DSI);
> +	if (ret) {
> +		DRM_ERROR("Failed to encoder init to drm\n");
> +		return ret;
> +	}
> +
> +	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +	if (ret)
> +		goto err_cleanup_encoder;
> +
> +	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +	if (IS_ERR(dsi->connector)) {
> +		DRM_ERROR("Unable to create bridge connector\n");
> +		ret = PTR_ERR(dsi->connector);
> +		goto err_cleanup_encoder;
> +	}
> +	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +	return 0;
> +
> +err_cleanup_encoder:
> +	drm_encoder_cleanup(&dsi->encoder);
> +	return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +	int ret;
> +	struct drm_device *drm = data;
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	ret = mtk_dsi_encoder_init(drm, dsi);
> +	if (ret)
> +		return ret;
> +
> +	return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +			   void *data)
> +{
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +	.bind = mtk_dsi_bind,
> +	.unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -	int ret;
> -
> -	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -				      DRM_MODE_ENCODER_DSI);
> -	if (ret) {
> -		DRM_ERROR("Failed to encoder init to drm\n");
> -		return ret;
> -	}
> -
> -	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -	if (ret)
> -		goto err_cleanup_encoder;
> -
> -	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -	if (IS_ERR(dsi->connector)) {
> -		DRM_ERROR("Unable to create bridge connector\n");
> -		ret = PTR_ERR(dsi->connector);
> -		goto err_cleanup_encoder;
> -	}
> -	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -	return 0;
> -
> -err_cleanup_encoder:
> -	drm_encoder_cleanup(&dsi->encoder);
> -	return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -	int ret;
> -	struct drm_device *drm = data;
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	ret = mtk_dsi_encoder_init(drm, dsi);
> -	if (ret)
> -		return ret;
> -
> -	return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -			   void *data)
> -{
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -	.bind = mtk_dsi_bind,
> -	.unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;
> -- 
> 2.33.1
> 
> 
> -- 
> To unsubscribe, send mail to kernel-unsubscribe@lists.collabora.co.uk.

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-09 14:48   ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 24+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-02-09 14:48 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: chunkuang.hu, airlied, linux-kernel, dri-devel, andrzej.hajda,
	linux-mediatek, stable, matthias.bgg, kernel, linux-arm-kernel,
	Jagan Teki

Hi Angelo,

On Mon, Jan 31, 2022 at 09:55:20AM +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

Thanks,
Nícolas

> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +	int ret;
> +
> +	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +				      DRM_MODE_ENCODER_DSI);
> +	if (ret) {
> +		DRM_ERROR("Failed to encoder init to drm\n");
> +		return ret;
> +	}
> +
> +	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +	if (ret)
> +		goto err_cleanup_encoder;
> +
> +	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +	if (IS_ERR(dsi->connector)) {
> +		DRM_ERROR("Unable to create bridge connector\n");
> +		ret = PTR_ERR(dsi->connector);
> +		goto err_cleanup_encoder;
> +	}
> +	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +	return 0;
> +
> +err_cleanup_encoder:
> +	drm_encoder_cleanup(&dsi->encoder);
> +	return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +	int ret;
> +	struct drm_device *drm = data;
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	ret = mtk_dsi_encoder_init(drm, dsi);
> +	if (ret)
> +		return ret;
> +
> +	return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +			   void *data)
> +{
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +	.bind = mtk_dsi_bind,
> +	.unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -	int ret;
> -
> -	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -				      DRM_MODE_ENCODER_DSI);
> -	if (ret) {
> -		DRM_ERROR("Failed to encoder init to drm\n");
> -		return ret;
> -	}
> -
> -	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -	if (ret)
> -		goto err_cleanup_encoder;
> -
> -	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -	if (IS_ERR(dsi->connector)) {
> -		DRM_ERROR("Unable to create bridge connector\n");
> -		ret = PTR_ERR(dsi->connector);
> -		goto err_cleanup_encoder;
> -	}
> -	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -	return 0;
> -
> -err_cleanup_encoder:
> -	drm_encoder_cleanup(&dsi->encoder);
> -	return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -	int ret;
> -	struct drm_device *drm = data;
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	ret = mtk_dsi_encoder_init(drm, dsi);
> -	if (ret)
> -		return ret;
> -
> -	return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -			   void *data)
> -{
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -	.bind = mtk_dsi_bind,
> -	.unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;
> -- 
> 2.33.1
> 
> 
> -- 
> To unsubscribe, send mail to kernel-unsubscribe@lists.collabora.co.uk.

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-09 14:48   ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 24+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-02-09 14:48 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	chunkuang.hu, p.zabel, airlied, daniel, matthias.bgg, kernel,
	andrzej.hajda, stable, Jagan Teki

Hi Angelo,

On Mon, Jan 31, 2022 at 09:55:20AM +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

Thanks,
Nícolas

> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +	int ret;
> +
> +	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +				      DRM_MODE_ENCODER_DSI);
> +	if (ret) {
> +		DRM_ERROR("Failed to encoder init to drm\n");
> +		return ret;
> +	}
> +
> +	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +	if (ret)
> +		goto err_cleanup_encoder;
> +
> +	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +	if (IS_ERR(dsi->connector)) {
> +		DRM_ERROR("Unable to create bridge connector\n");
> +		ret = PTR_ERR(dsi->connector);
> +		goto err_cleanup_encoder;
> +	}
> +	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +	return 0;
> +
> +err_cleanup_encoder:
> +	drm_encoder_cleanup(&dsi->encoder);
> +	return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +	int ret;
> +	struct drm_device *drm = data;
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	ret = mtk_dsi_encoder_init(drm, dsi);
> +	if (ret)
> +		return ret;
> +
> +	return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +			   void *data)
> +{
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +	.bind = mtk_dsi_bind,
> +	.unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -	int ret;
> -
> -	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -				      DRM_MODE_ENCODER_DSI);
> -	if (ret) {
> -		DRM_ERROR("Failed to encoder init to drm\n");
> -		return ret;
> -	}
> -
> -	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -	if (ret)
> -		goto err_cleanup_encoder;
> -
> -	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -	if (IS_ERR(dsi->connector)) {
> -		DRM_ERROR("Unable to create bridge connector\n");
> -		ret = PTR_ERR(dsi->connector);
> -		goto err_cleanup_encoder;
> -	}
> -	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -	return 0;
> -
> -err_cleanup_encoder:
> -	drm_encoder_cleanup(&dsi->encoder);
> -	return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -	int ret;
> -	struct drm_device *drm = data;
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	ret = mtk_dsi_encoder_init(drm, dsi);
> -	if (ret)
> -		return ret;
> -
> -	return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -			   void *data)
> -{
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -	.bind = mtk_dsi_bind,
> -	.unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;
> -- 
> 2.33.1
> 
> 
> -- 
> To unsubscribe, send mail to kernel-unsubscribe@lists.collabora.co.uk.

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-09 14:48   ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 24+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-02-09 14:48 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: dri-devel, linux-mediatek, linux-arm-kernel, linux-kernel,
	chunkuang.hu, p.zabel, airlied, daniel, matthias.bgg, kernel,
	andrzej.hajda, stable, Jagan Teki

Hi Angelo,

On Mon, Jan 31, 2022 at 09:55:20AM +0100, AngeloGioacchino Del Regno wrote:
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
> 
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).
> 
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>

Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>

Thanks,
Nícolas

> 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>  	mtk_dsi_poweroff(dsi);
>  }
>  
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +	int ret;
> +
> +	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +				      DRM_MODE_ENCODER_DSI);
> +	if (ret) {
> +		DRM_ERROR("Failed to encoder init to drm\n");
> +		return ret;
> +	}
> +
> +	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +	if (ret)
> +		goto err_cleanup_encoder;
> +
> +	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +	if (IS_ERR(dsi->connector)) {
> +		DRM_ERROR("Unable to create bridge connector\n");
> +		ret = PTR_ERR(dsi->connector);
> +		goto err_cleanup_encoder;
> +	}
> +	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +	return 0;
> +
> +err_cleanup_encoder:
> +	drm_encoder_cleanup(&dsi->encoder);
> +	return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +	int ret;
> +	struct drm_device *drm = data;
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	ret = mtk_dsi_encoder_init(drm, dsi);
> +	if (ret)
> +		return ret;
> +
> +	return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +			   void *data)
> +{
> +	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +	drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +	.bind = mtk_dsi_bind,
> +	.unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>  			       struct mipi_dsi_device *device)
>  {
>  	struct mtk_dsi *dsi = host_to_dsi(host);
> +	struct device *dev = host->dev;
> +	int ret;
>  
>  	dsi->lanes = device->lanes;
>  	dsi->format = device->format;
>  	dsi->mode_flags = device->mode_flags;
> +	dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +	if (IS_ERR(dsi->next_bridge))
> +		return PTR_ERR(dsi->next_bridge);
> +
> +	drm_bridge_add(&dsi->bridge);
> +
> +	ret = component_add(host->dev, &mtk_dsi_component_ops);
> +	if (ret) {
> +		DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +		drm_bridge_remove(&dsi->bridge);
> +		return ret;
> +	}
>  
>  	return 0;
>  }
>  
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +			       struct mipi_dsi_device *device)
> +{
> +	struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +	component_del(host->dev, &mtk_dsi_component_ops);
> +	drm_bridge_remove(&dsi->bridge);
> +	return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>  
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>  	.attach = mtk_dsi_host_attach,
> +	.detach = mtk_dsi_host_detach,
>  	.transfer = mtk_dsi_host_transfer,
>  };
>  
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -	int ret;
> -
> -	ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -				      DRM_MODE_ENCODER_DSI);
> -	if (ret) {
> -		DRM_ERROR("Failed to encoder init to drm\n");
> -		return ret;
> -	}
> -
> -	dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -	if (ret)
> -		goto err_cleanup_encoder;
> -
> -	dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -	if (IS_ERR(dsi->connector)) {
> -		DRM_ERROR("Unable to create bridge connector\n");
> -		ret = PTR_ERR(dsi->connector);
> -		goto err_cleanup_encoder;
> -	}
> -	drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -	return 0;
> -
> -err_cleanup_encoder:
> -	drm_encoder_cleanup(&dsi->encoder);
> -	return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -	int ret;
> -	struct drm_device *drm = data;
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	ret = mtk_dsi_encoder_init(drm, dsi);
> -	if (ret)
> -		return ret;
> -
> -	return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -			   void *data)
> -{
> -	struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -	drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -	.bind = mtk_dsi_bind,
> -	.unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>  	struct mtk_dsi *dsi;
>  	struct device *dev = &pdev->dev;
> -	struct drm_panel *panel;
>  	struct resource *regs;
>  	int irq_num;
>  	int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -					  &panel, &dsi->next_bridge);
> -	if (ret)
> -		goto err_unregister_host;
> -
> -	if (panel) {
> -		dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -		if (IS_ERR(dsi->next_bridge)) {
> -			ret = PTR_ERR(dsi->next_bridge);
> -			goto err_unregister_host;
> -		}
> -	}
> -
>  	dsi->driver_data = of_device_get_match_data(dev);
>  
>  	dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>  	dsi->bridge.of_node = dev->of_node;
>  	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>  
> -	drm_bridge_add(&dsi->bridge);
> -
> -	ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -	if (ret) {
> -		dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -		goto err_unregister_host;
> -	}
> -
>  	return 0;
>  
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>  	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>  
>  	mtk_output_dsi_disable(dsi);
> -	drm_bridge_remove(&dsi->bridge);
> -	component_del(&pdev->dev, &mtk_dsi_component_ops);
>  	mipi_dsi_host_unregister(&dsi->host);
>  
>  	return 0;
> -- 
> 2.33.1
> 
> 
> -- 
> To unsubscribe, send mail to kernel-unsubscribe@lists.collabora.co.uk.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
  2022-01-31  8:55 ` AngeloGioacchino Del Regno
  (?)
  (?)
@ 2022-02-09 15:06   ` Chun-Kuang Hu
  -1 siblings, 0 replies; 24+ messages in thread
From: Chun-Kuang Hu @ 2022-02-09 15:06 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: DRI Development, Chun-Kuang Hu, David Airlie, linux-kernel,
	stable, andrzej.hajda, moderated list:ARM/Mediatek SoC support,
	Jagan Teki, Matthias Brugger, Collabora Kernel ML, Linux ARM

 Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 於
2022年1月31日 週一 下午4:55寫道:
>
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
>
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).

Applied to mediatek-drm-fixes[1], thanks.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-fixes

Regards,
Chun-Kuang.

>
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>         mtk_dsi_poweroff(dsi);
>  }
>
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +       int ret;
> +
> +       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +                                     DRM_MODE_ENCODER_DSI);
> +       if (ret) {
> +               DRM_ERROR("Failed to encoder init to drm\n");
> +               return ret;
> +       }
> +
> +       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +       if (ret)
> +               goto err_cleanup_encoder;
> +
> +       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +       if (IS_ERR(dsi->connector)) {
> +               DRM_ERROR("Unable to create bridge connector\n");
> +               ret = PTR_ERR(dsi->connector);
> +               goto err_cleanup_encoder;
> +       }
> +       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +       return 0;
> +
> +err_cleanup_encoder:
> +       drm_encoder_cleanup(&dsi->encoder);
> +       return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +       int ret;
> +       struct drm_device *drm = data;
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       ret = mtk_dsi_encoder_init(drm, dsi);
> +       if (ret)
> +               return ret;
> +
> +       return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +                          void *data)
> +{
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +       .bind = mtk_dsi_bind,
> +       .unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>                                struct mipi_dsi_device *device)
>  {
>         struct mtk_dsi *dsi = host_to_dsi(host);
> +       struct device *dev = host->dev;
> +       int ret;
>
>         dsi->lanes = device->lanes;
>         dsi->format = device->format;
>         dsi->mode_flags = device->mode_flags;
> +       dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +       if (IS_ERR(dsi->next_bridge))
> +               return PTR_ERR(dsi->next_bridge);
> +
> +       drm_bridge_add(&dsi->bridge);
> +
> +       ret = component_add(host->dev, &mtk_dsi_component_ops);
> +       if (ret) {
> +               DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +               drm_bridge_remove(&dsi->bridge);
> +               return ret;
> +       }
>
>         return 0;
>  }
>
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +                              struct mipi_dsi_device *device)
> +{
> +       struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +       component_del(host->dev, &mtk_dsi_component_ops);
> +       drm_bridge_remove(&dsi->bridge);
> +       return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>         .attach = mtk_dsi_host_attach,
> +       .detach = mtk_dsi_host_detach,
>         .transfer = mtk_dsi_host_transfer,
>  };
>
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -       int ret;
> -
> -       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -                                     DRM_MODE_ENCODER_DSI);
> -       if (ret) {
> -               DRM_ERROR("Failed to encoder init to drm\n");
> -               return ret;
> -       }
> -
> -       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -       if (ret)
> -               goto err_cleanup_encoder;
> -
> -       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -       if (IS_ERR(dsi->connector)) {
> -               DRM_ERROR("Unable to create bridge connector\n");
> -               ret = PTR_ERR(dsi->connector);
> -               goto err_cleanup_encoder;
> -       }
> -       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -       return 0;
> -
> -err_cleanup_encoder:
> -       drm_encoder_cleanup(&dsi->encoder);
> -       return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -       int ret;
> -       struct drm_device *drm = data;
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       ret = mtk_dsi_encoder_init(drm, dsi);
> -       if (ret)
> -               return ret;
> -
> -       return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -                          void *data)
> -{
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -       .bind = mtk_dsi_bind,
> -       .unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>         struct mtk_dsi *dsi;
>         struct device *dev = &pdev->dev;
> -       struct drm_panel *panel;
>         struct resource *regs;
>         int irq_num;
>         int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>                 return ret;
>         }
>
> -       ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -                                         &panel, &dsi->next_bridge);
> -       if (ret)
> -               goto err_unregister_host;
> -
> -       if (panel) {
> -               dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -               if (IS_ERR(dsi->next_bridge)) {
> -                       ret = PTR_ERR(dsi->next_bridge);
> -                       goto err_unregister_host;
> -               }
> -       }
> -
>         dsi->driver_data = of_device_get_match_data(dev);
>
>         dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>         dsi->bridge.of_node = dev->of_node;
>         dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>
> -       drm_bridge_add(&dsi->bridge);
> -
> -       ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -       if (ret) {
> -               dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -               goto err_unregister_host;
> -       }
> -
>         return 0;
>
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>         struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>
>         mtk_output_dsi_disable(dsi);
> -       drm_bridge_remove(&dsi->bridge);
> -       component_del(&pdev->dev, &mtk_dsi_component_ops);
>         mipi_dsi_host_unregister(&dsi->host);
>
>         return 0;
> --
> 2.33.1
>

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-09 15:06   ` Chun-Kuang Hu
  0 siblings, 0 replies; 24+ messages in thread
From: Chun-Kuang Hu @ 2022-02-09 15:06 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: Chun-Kuang Hu, David Airlie, linux-kernel, stable,
	moderated list:ARM/Mediatek SoC support, DRI Development,
	andrzej.hajda, Matthias Brugger, Collabora Kernel ML, Linux ARM,
	Jagan Teki

 Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 於
2022年1月31日 週一 下午4:55寫道:
>
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
>
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).

Applied to mediatek-drm-fixes[1], thanks.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-fixes

Regards,
Chun-Kuang.

>
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>         mtk_dsi_poweroff(dsi);
>  }
>
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +       int ret;
> +
> +       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +                                     DRM_MODE_ENCODER_DSI);
> +       if (ret) {
> +               DRM_ERROR("Failed to encoder init to drm\n");
> +               return ret;
> +       }
> +
> +       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +       if (ret)
> +               goto err_cleanup_encoder;
> +
> +       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +       if (IS_ERR(dsi->connector)) {
> +               DRM_ERROR("Unable to create bridge connector\n");
> +               ret = PTR_ERR(dsi->connector);
> +               goto err_cleanup_encoder;
> +       }
> +       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +       return 0;
> +
> +err_cleanup_encoder:
> +       drm_encoder_cleanup(&dsi->encoder);
> +       return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +       int ret;
> +       struct drm_device *drm = data;
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       ret = mtk_dsi_encoder_init(drm, dsi);
> +       if (ret)
> +               return ret;
> +
> +       return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +                          void *data)
> +{
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +       .bind = mtk_dsi_bind,
> +       .unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>                                struct mipi_dsi_device *device)
>  {
>         struct mtk_dsi *dsi = host_to_dsi(host);
> +       struct device *dev = host->dev;
> +       int ret;
>
>         dsi->lanes = device->lanes;
>         dsi->format = device->format;
>         dsi->mode_flags = device->mode_flags;
> +       dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +       if (IS_ERR(dsi->next_bridge))
> +               return PTR_ERR(dsi->next_bridge);
> +
> +       drm_bridge_add(&dsi->bridge);
> +
> +       ret = component_add(host->dev, &mtk_dsi_component_ops);
> +       if (ret) {
> +               DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +               drm_bridge_remove(&dsi->bridge);
> +               return ret;
> +       }
>
>         return 0;
>  }
>
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +                              struct mipi_dsi_device *device)
> +{
> +       struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +       component_del(host->dev, &mtk_dsi_component_ops);
> +       drm_bridge_remove(&dsi->bridge);
> +       return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>         .attach = mtk_dsi_host_attach,
> +       .detach = mtk_dsi_host_detach,
>         .transfer = mtk_dsi_host_transfer,
>  };
>
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -       int ret;
> -
> -       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -                                     DRM_MODE_ENCODER_DSI);
> -       if (ret) {
> -               DRM_ERROR("Failed to encoder init to drm\n");
> -               return ret;
> -       }
> -
> -       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -       if (ret)
> -               goto err_cleanup_encoder;
> -
> -       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -       if (IS_ERR(dsi->connector)) {
> -               DRM_ERROR("Unable to create bridge connector\n");
> -               ret = PTR_ERR(dsi->connector);
> -               goto err_cleanup_encoder;
> -       }
> -       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -       return 0;
> -
> -err_cleanup_encoder:
> -       drm_encoder_cleanup(&dsi->encoder);
> -       return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -       int ret;
> -       struct drm_device *drm = data;
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       ret = mtk_dsi_encoder_init(drm, dsi);
> -       if (ret)
> -               return ret;
> -
> -       return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -                          void *data)
> -{
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -       .bind = mtk_dsi_bind,
> -       .unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>         struct mtk_dsi *dsi;
>         struct device *dev = &pdev->dev;
> -       struct drm_panel *panel;
>         struct resource *regs;
>         int irq_num;
>         int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>                 return ret;
>         }
>
> -       ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -                                         &panel, &dsi->next_bridge);
> -       if (ret)
> -               goto err_unregister_host;
> -
> -       if (panel) {
> -               dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -               if (IS_ERR(dsi->next_bridge)) {
> -                       ret = PTR_ERR(dsi->next_bridge);
> -                       goto err_unregister_host;
> -               }
> -       }
> -
>         dsi->driver_data = of_device_get_match_data(dev);
>
>         dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>         dsi->bridge.of_node = dev->of_node;
>         dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>
> -       drm_bridge_add(&dsi->bridge);
> -
> -       ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -       if (ret) {
> -               dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -               goto err_unregister_host;
> -       }
> -
>         return 0;
>
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>         struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>
>         mtk_output_dsi_disable(dsi);
> -       drm_bridge_remove(&dsi->bridge);
> -       component_del(&pdev->dev, &mtk_dsi_component_ops);
>         mipi_dsi_host_unregister(&dsi->host);
>
>         return 0;
> --
> 2.33.1
>

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-09 15:06   ` Chun-Kuang Hu
  0 siblings, 0 replies; 24+ messages in thread
From: Chun-Kuang Hu @ 2022-02-09 15:06 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: DRI Development, Chun-Kuang Hu, David Airlie, linux-kernel,
	stable, andrzej.hajda, moderated list:ARM/Mediatek SoC support,
	Jagan Teki, Matthias Brugger, Collabora Kernel ML, Linux ARM

 Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 於
2022年1月31日 週一 下午4:55寫道:
>
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
>
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).

Applied to mediatek-drm-fixes[1], thanks.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-fixes

Regards,
Chun-Kuang.

>
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>         mtk_dsi_poweroff(dsi);
>  }
>
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +       int ret;
> +
> +       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +                                     DRM_MODE_ENCODER_DSI);
> +       if (ret) {
> +               DRM_ERROR("Failed to encoder init to drm\n");
> +               return ret;
> +       }
> +
> +       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +       if (ret)
> +               goto err_cleanup_encoder;
> +
> +       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +       if (IS_ERR(dsi->connector)) {
> +               DRM_ERROR("Unable to create bridge connector\n");
> +               ret = PTR_ERR(dsi->connector);
> +               goto err_cleanup_encoder;
> +       }
> +       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +       return 0;
> +
> +err_cleanup_encoder:
> +       drm_encoder_cleanup(&dsi->encoder);
> +       return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +       int ret;
> +       struct drm_device *drm = data;
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       ret = mtk_dsi_encoder_init(drm, dsi);
> +       if (ret)
> +               return ret;
> +
> +       return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +                          void *data)
> +{
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +       .bind = mtk_dsi_bind,
> +       .unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>                                struct mipi_dsi_device *device)
>  {
>         struct mtk_dsi *dsi = host_to_dsi(host);
> +       struct device *dev = host->dev;
> +       int ret;
>
>         dsi->lanes = device->lanes;
>         dsi->format = device->format;
>         dsi->mode_flags = device->mode_flags;
> +       dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +       if (IS_ERR(dsi->next_bridge))
> +               return PTR_ERR(dsi->next_bridge);
> +
> +       drm_bridge_add(&dsi->bridge);
> +
> +       ret = component_add(host->dev, &mtk_dsi_component_ops);
> +       if (ret) {
> +               DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +               drm_bridge_remove(&dsi->bridge);
> +               return ret;
> +       }
>
>         return 0;
>  }
>
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +                              struct mipi_dsi_device *device)
> +{
> +       struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +       component_del(host->dev, &mtk_dsi_component_ops);
> +       drm_bridge_remove(&dsi->bridge);
> +       return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>         .attach = mtk_dsi_host_attach,
> +       .detach = mtk_dsi_host_detach,
>         .transfer = mtk_dsi_host_transfer,
>  };
>
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -       int ret;
> -
> -       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -                                     DRM_MODE_ENCODER_DSI);
> -       if (ret) {
> -               DRM_ERROR("Failed to encoder init to drm\n");
> -               return ret;
> -       }
> -
> -       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -       if (ret)
> -               goto err_cleanup_encoder;
> -
> -       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -       if (IS_ERR(dsi->connector)) {
> -               DRM_ERROR("Unable to create bridge connector\n");
> -               ret = PTR_ERR(dsi->connector);
> -               goto err_cleanup_encoder;
> -       }
> -       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -       return 0;
> -
> -err_cleanup_encoder:
> -       drm_encoder_cleanup(&dsi->encoder);
> -       return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -       int ret;
> -       struct drm_device *drm = data;
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       ret = mtk_dsi_encoder_init(drm, dsi);
> -       if (ret)
> -               return ret;
> -
> -       return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -                          void *data)
> -{
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -       .bind = mtk_dsi_bind,
> -       .unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>         struct mtk_dsi *dsi;
>         struct device *dev = &pdev->dev;
> -       struct drm_panel *panel;
>         struct resource *regs;
>         int irq_num;
>         int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>                 return ret;
>         }
>
> -       ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -                                         &panel, &dsi->next_bridge);
> -       if (ret)
> -               goto err_unregister_host;
> -
> -       if (panel) {
> -               dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -               if (IS_ERR(dsi->next_bridge)) {
> -                       ret = PTR_ERR(dsi->next_bridge);
> -                       goto err_unregister_host;
> -               }
> -       }
> -
>         dsi->driver_data = of_device_get_match_data(dev);
>
>         dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>         dsi->bridge.of_node = dev->of_node;
>         dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>
> -       drm_bridge_add(&dsi->bridge);
> -
> -       ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -       if (ret) {
> -               dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -               goto err_unregister_host;
> -       }
> -
>         return 0;
>
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>         struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>
>         mtk_output_dsi_disable(dsi);
> -       drm_bridge_remove(&dsi->bridge);
> -       component_del(&pdev->dev, &mtk_dsi_component_ops);
>         mipi_dsi_host_unregister(&dsi->host);
>
>         return 0;
> --
> 2.33.1
>

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

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

* Re: [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
@ 2022-02-09 15:06   ` Chun-Kuang Hu
  0 siblings, 0 replies; 24+ messages in thread
From: Chun-Kuang Hu @ 2022-02-09 15:06 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: DRI Development, Chun-Kuang Hu, David Airlie, linux-kernel,
	stable, andrzej.hajda, moderated list:ARM/Mediatek SoC support,
	Jagan Teki, Matthias Brugger, Collabora Kernel ML, Linux ARM

 Hi, Angelo:

AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 於
2022年1月31日 週一 下午4:55寫道:
>
> DRM bridge drivers are now attaching their DSI device at probe time,
> which requires us to register our DSI host in order to let the bridge
> to probe: this recently started producing an endless -EPROBE_DEFER
> loop on some machines that are using external bridges, like the
> parade-ps8640, found on the ACER Chromebook R13.
>
> Now that the DSI hosts/devices probe sequence is documented, we can
> do adjustments to the mtk_dsi driver as to both fix now and make sure
> to avoid this situation in the future: for this, following what is
> documented in drm_bridge.c, move the mtk_dsi component_add() to the
> mtk_dsi_ops.attach callback and delete it in the detach callback;
> keeping in mind that we are registering a drm_bridge for our DSI,
> which is only used/attached if the DSI Host is bound, it wouldn't
> make sense to keep adding our bridge at probe time (as it would
> be useless to have it if mtk_dsi_ops.attach() fails!), so also move
> that one to the dsi host attach function (and remove it in detach).

Applied to mediatek-drm-fixes[1], thanks.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-fixes

Regards,
Chun-Kuang.

>
> Cc: <stable@vger.kernel.org> # 5.15.x
> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
> Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
>
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
>  1 file changed, 84 insertions(+), 83 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 5d90d2eb0019..bced4c7d668e 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
>         mtk_dsi_poweroff(dsi);
>  }
>
> +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> +{
> +       int ret;
> +
> +       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> +                                     DRM_MODE_ENCODER_DSI);
> +       if (ret) {
> +               DRM_ERROR("Failed to encoder init to drm\n");
> +               return ret;
> +       }
> +
> +       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> +
> +       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> +                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +       if (ret)
> +               goto err_cleanup_encoder;
> +
> +       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> +       if (IS_ERR(dsi->connector)) {
> +               DRM_ERROR("Unable to create bridge connector\n");
> +               ret = PTR_ERR(dsi->connector);
> +               goto err_cleanup_encoder;
> +       }
> +       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> +
> +       return 0;
> +
> +err_cleanup_encoder:
> +       drm_encoder_cleanup(&dsi->encoder);
> +       return ret;
> +}
> +
> +static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> +{
> +       int ret;
> +       struct drm_device *drm = data;
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       ret = mtk_dsi_encoder_init(drm, dsi);
> +       if (ret)
> +               return ret;
> +
> +       return device_reset_optional(dev);
> +}
> +
> +static void mtk_dsi_unbind(struct device *dev, struct device *master,
> +                          void *data)
> +{
> +       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> +
> +       drm_encoder_cleanup(&dsi->encoder);
> +}
> +
> +static const struct component_ops mtk_dsi_component_ops = {
> +       .bind = mtk_dsi_bind,
> +       .unbind = mtk_dsi_unbind,
> +};
> +
>  static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>                                struct mipi_dsi_device *device)
>  {
>         struct mtk_dsi *dsi = host_to_dsi(host);
> +       struct device *dev = host->dev;
> +       int ret;
>
>         dsi->lanes = device->lanes;
>         dsi->format = device->format;
>         dsi->mode_flags = device->mode_flags;
> +       dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +       if (IS_ERR(dsi->next_bridge))
> +               return PTR_ERR(dsi->next_bridge);
> +
> +       drm_bridge_add(&dsi->bridge);
> +
> +       ret = component_add(host->dev, &mtk_dsi_component_ops);
> +       if (ret) {
> +               DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> +               drm_bridge_remove(&dsi->bridge);
> +               return ret;
> +       }
>
>         return 0;
>  }
>
> +static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
> +                              struct mipi_dsi_device *device)
> +{
> +       struct mtk_dsi *dsi = host_to_dsi(host);
> +
> +       component_del(host->dev, &mtk_dsi_component_ops);
> +       drm_bridge_remove(&dsi->bridge);
> +       return 0;
> +}
> +
>  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
>
>  static const struct mipi_dsi_host_ops mtk_dsi_ops = {
>         .attach = mtk_dsi_host_attach,
> +       .detach = mtk_dsi_host_detach,
>         .transfer = mtk_dsi_host_transfer,
>  };
>
> -static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> -{
> -       int ret;
> -
> -       ret = drm_simple_encoder_init(drm, &dsi->encoder,
> -                                     DRM_MODE_ENCODER_DSI);
> -       if (ret) {
> -               DRM_ERROR("Failed to encoder init to drm\n");
> -               return ret;
> -       }
> -
> -       dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
> -
> -       ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
> -                               DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -       if (ret)
> -               goto err_cleanup_encoder;
> -
> -       dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> -       if (IS_ERR(dsi->connector)) {
> -               DRM_ERROR("Unable to create bridge connector\n");
> -               ret = PTR_ERR(dsi->connector);
> -               goto err_cleanup_encoder;
> -       }
> -       drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
> -
> -       return 0;
> -
> -err_cleanup_encoder:
> -       drm_encoder_cleanup(&dsi->encoder);
> -       return ret;
> -}
> -
> -static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
> -{
> -       int ret;
> -       struct drm_device *drm = data;
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       ret = mtk_dsi_encoder_init(drm, dsi);
> -       if (ret)
> -               return ret;
> -
> -       return device_reset_optional(dev);
> -}
> -
> -static void mtk_dsi_unbind(struct device *dev, struct device *master,
> -                          void *data)
> -{
> -       struct mtk_dsi *dsi = dev_get_drvdata(dev);
> -
> -       drm_encoder_cleanup(&dsi->encoder);
> -}
> -
> -static const struct component_ops mtk_dsi_component_ops = {
> -       .bind = mtk_dsi_bind,
> -       .unbind = mtk_dsi_unbind,
> -};
> -
>  static int mtk_dsi_probe(struct platform_device *pdev)
>  {
>         struct mtk_dsi *dsi;
>         struct device *dev = &pdev->dev;
> -       struct drm_panel *panel;
>         struct resource *regs;
>         int irq_num;
>         int ret;
> @@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>                 return ret;
>         }
>
> -       ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
> -                                         &panel, &dsi->next_bridge);
> -       if (ret)
> -               goto err_unregister_host;
> -
> -       if (panel) {
> -               dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
> -               if (IS_ERR(dsi->next_bridge)) {
> -                       ret = PTR_ERR(dsi->next_bridge);
> -                       goto err_unregister_host;
> -               }
> -       }
> -
>         dsi->driver_data = of_device_get_match_data(dev);
>
>         dsi->engine_clk = devm_clk_get(dev, "engine");
> @@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
>         dsi->bridge.of_node = dev->of_node;
>         dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
>
> -       drm_bridge_add(&dsi->bridge);
> -
> -       ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
> -       if (ret) {
> -               dev_err(&pdev->dev, "failed to add component: %d\n", ret);
> -               goto err_unregister_host;
> -       }
> -
>         return 0;
>
>  err_unregister_host:
> @@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
>         struct mtk_dsi *dsi = platform_get_drvdata(pdev);
>
>         mtk_output_dsi_disable(dsi);
> -       drm_bridge_remove(&dsi->bridge);
> -       component_del(&pdev->dev, &mtk_dsi_component_ops);
>         mipi_dsi_host_unregister(&dsi->host);
>
>         return 0;
> --
> 2.33.1
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2022-02-09 15:08 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-31  8:55 [PATCH v4] drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge AngeloGioacchino Del Regno
2022-01-31  8:55 ` AngeloGioacchino Del Regno
2022-01-31  8:55 ` AngeloGioacchino Del Regno
2022-01-31  8:55 ` AngeloGioacchino Del Regno
2022-02-08  8:20 ` CK Hu
2022-02-08  8:20   ` CK Hu
2022-02-08  8:20   ` CK Hu
2022-02-08  8:20   ` CK Hu
2022-02-08  8:32   ` CK Hu
2022-02-08  8:32     ` CK Hu
2022-02-08  8:32     ` CK Hu
2022-02-08  8:32     ` CK Hu
2022-02-08  9:03     ` AngeloGioacchino Del Regno
2022-02-08  9:03       ` AngeloGioacchino Del Regno
2022-02-08  9:03       ` AngeloGioacchino Del Regno
2022-02-08  9:03       ` AngeloGioacchino Del Regno
2022-02-09 14:48 ` Nícolas F. R. A. Prado
2022-02-09 14:48   ` Nícolas F. R. A. Prado
2022-02-09 14:48   ` Nícolas F. R. A. Prado
2022-02-09 14:48   ` Nícolas F. R. A. Prado
2022-02-09 15:06 ` Chun-Kuang Hu
2022-02-09 15:06   ` Chun-Kuang Hu
2022-02-09 15:06   ` Chun-Kuang Hu
2022-02-09 15:06   ` Chun-Kuang Hu

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.