Received: by 2002:a05:7412:8d11:b0:fa:4934:9f with SMTP id bj17csp439245rdb; Mon, 15 Jan 2024 02:09:51 -0800 (PST) X-Google-Smtp-Source: AGHT+IE7csApY4O34ccOYHqByrCrr34VyR5oP+UmDOf7Kbg2EsInTIGsYjoFmXUgKOl1ORSYNOcM X-Received: by 2002:a05:6870:5253:b0:208:967e:6576 with SMTP id o19-20020a056870525300b00208967e6576mr2542664oai.25.1705313391002; Mon, 15 Jan 2024 02:09:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1705313390; cv=none; d=google.com; s=arc-20160816; b=hdRzfBKxDVMHvFGu9wNXdgNyrY6vOZERVm57fklmOQ+AnPiCOCPfm81dSuuLjxmWCy iwbE0L4ILA6Hwy5PSdsQbRNyXFwSH16E7PDgzo88MBUYCO/7FHStYAl8eg6YK7rKea7e BmYa9MwFbQHcTZNo5Ooz9mx3L47o57nrS4S711hR9bG4xzvGk4ferr5VViE/GwvsFv44 nDGbez07foqXVdWnJuH82kWeBSfpdRWIwKcvX3YOWhjamI0EjVRmQ5r/4W5h4Grl0xdH gJQImQz8DWLw8mMAfib+4kjp7D+Yxoo6Cf89/slCoHz2WB48Tf6+QS9WVz8oAWpYUr1B uoAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=gqfPD9z4AVA1wpXnxNQ/rYlAYn6+Aoc0Gq6RwyHId7Y=; fh=ihyp0KS7qf0TyyJG2wZwWWoKrEtAyV4Y/E+ty/n/UNI=; b=LiiJc8TiNaoKOougbllDCrwWpUULpNhv64qd8aDgOPcZK4AiAQq4am7QOIFiratOAN YSaeNvVpmheUfI1RV6MSedh5VoUZDRvAwSghkNRdU7GB9Vpp15qb23vVpwZABzwb0MfH Lnuq+1tcv2fT2c4E6D/refQNyTtpIYzCb4eKDkV9fg47FGLA8gLK5WAgXIOIAdBDbf1k +U8nV8fKwYMNmeNMPa8mebXTgJrfQefr3bwuDqHpvwtsW2kAPVLjavxAMAnkJuDH3MBW tuK20yC5ClFd50AfiFg8OdXGDTzdPKNCGIvzpL2UtkQ9X+pTpL+RYDOE6DFZXgOe6wn5 Ju+g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel+bounces-25857-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-25857-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=sntech.de Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id s188-20020a6377c5000000b005c65e697bc4si8973723pgc.550.2024.01.15.02.09.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jan 2024 02:09:50 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-25857-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel+bounces-25857-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-25857-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=sntech.de Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 88E27B21781 for ; Mon, 15 Jan 2024 10:08:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9D3FE28DD1; Mon, 15 Jan 2024 10:08:11 +0000 (UTC) Received: from gloria.sntech.de (gloria.sntech.de [185.11.138.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CDC532206D for ; Mon, 15 Jan 2024 10:08:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sntech.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sntech.de Received: from i5e860cd7.versanet.de ([94.134.12.215] helo=diego.localnet) by gloria.sntech.de with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rPJsC-00005J-QB; Mon, 15 Jan 2024 11:07:16 +0100 From: Heiko =?ISO-8859-1?Q?St=FCbner?= To: Farouk Bouabid , victor.liu@nxp.com, andrzej.hajda@intel.com, rfoss@kernel.org, jonas@kwiboo.se, jernej.skrabec@gmail.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com, daniel@ffwll.ch, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, khilman@baylibre.com, jbrunet@baylibre.com, martin.blumenstingl@googlemail.com, hjc@rock-chips.com, yannick.fertre@foss.st.com, raphael.gallais-pou@foss.st.com, philippe.cornu@foss.st.com, mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, neil.armstrong@linaro.org Cc: quentin.schulz@theobroma-systems.com, bouabid.farouk97@gmail.com Subject: Re: [PATCH] drm/bridge: synopsys: dw-mipi-dsi: fix deferred dsi host probe breaks dsi device probe Date: Mon, 15 Jan 2024 11:07:14 +0100 Message-ID: <8542394.JRmrKFJ9eK@diego> In-Reply-To: <9dd100de-6d33-4872-8619-1df6ee520c5a@linaro.org> References: <20240112180737.551318-1-farouk.bouabid@theobroma-systems.com> <9dd100de-6d33-4872-8619-1df6ee520c5a@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Am Montag, 15. Januar 2024, 09:45:10 CET schrieb neil.armstrong@linaro.org: > Hi, > > On 12/01/2024 19:07, Farouk Bouabid wrote: > > dw-mipi-dsi based drivers such as dw-mipi-dsi-rockchip or dw_mipi_dsi-stm > > depend on dw_mipi_dsi_probe() to initialize the dw_mipi_dsi driver > > structure (dmd pointer). This structure is only initialized once > > dw_mipi_dsi_probe() returns, creating the link between the locally created > > structure and the actual dmd pointer. > > > > Probing the dsi host can be deferred in case of dependency to a dsi > > phy-supply (eg. "rockchip,px30-dsi-dphy"). Meanwhile dsi-device drivers > > like panels (eg. "ltk050h3146w") can already be registered on the bus. > > In that case, when attempting, to register the dsi host from > > dw_mipi_dsi_probe() using mipi_dsi_host_register(), the panel probe is > > called with a dsi-host pointer that is still locally allocated in > > dw_mipi_dsi_probe(). > > > > While probing, the panel driver tries to attach to a dsi host > > (mipi_dsi_attach()) which calls in return for the specific dsi host > > attach hook. (e.g. dw_mipi_dsi_rockchip_host_attach()). > > dw_mipi_dsi_rockchip uses the component framework. > > In the attach hook, the host component is registered which calls in return > > for drm_bridge_attach() while trying to bind the component > > (dw_mipi_dsi_bind()) > > In meson_dw_mipi_dsi I simply fixed this by getting rid of components... If I remember correctly, the component element is there on Rockchip to facilitate running dual-dsi displays (1 panel driven by 2 dsi controllers), because it allows to wait for both controllers to have probed individually before trying to drive the display. Not sure if there is a better way to do that now. Heiko > > drm_bridge_attach() requires a valid drm bridge parameter. However, the > > drm bridge (&dmd->bridge) that will be passed, is not yet initialized since > > the dw_mipi_dsi_probe() has not yet returned. This call will fail with a > > fatal error (invalid bridge) causing the panel to not be probed again. > > > > To simplify the issue: drm_bridge_attach() depends on the result pointer > > of dw_mipi_dsi_probe(). > > While, if the dsi probe is deferred, drm_bridge_attach() is called before > > dw_mipi_dsi_probe() returns. > > > > drm_bridge_attach+0x14/0x1ac > > dw_mipi_dsi_bind+0x24/0x30 > > dw_mipi_dsi_rockchip_bind+0x258/0x378 > > component_bind_all+0x118/0x248 > > rockchip_drm_bind+0xb0/0x1f8 > > try_to_bring_up_aggregate_device+0x168/0x1d4 > > __component_add+0xa4/0x170 > > component_add+0x14/0x20 > > dw_mipi_dsi_rockchip_host_attach+0x54/0x144 > > dw_mipi_dsi_host_attach+0x9c/0xcc > > mipi_dsi_attach+0x28/0x3c > > ltk050h3146w_probe+0x10c/0x1a4 > > mipi_dsi_drv_probe+0x20/0x2c > > really_probe+0x148/0x2ac > > __driver_probe_device+0x78/0x12c > > driver_probe_device+0xdc/0x160 > > __device_attach_driver+0xb8/0x134 > > bus_for_each_drv+0x80/0xdc > > __device_attach+0xa8/0x1b0 > > device_initial_probe+0x14/0x20 > > bus_probe_device+0xa8/0xac > > device_add+0x5cc/0x778 > > mipi_dsi_device_register_full+0xd8/0x198 > > mipi_dsi_host_register+0x98/0x18c > > __dw_mipi_dsi_probe+0x290/0x35c > > dw_mipi_dsi_probe+0x10/0x6c > > dw_mipi_dsi_rockchip_probe+0x208/0x3e4 > > platform_probe+0x68/0xdc > > really_probe+0x148/0x2ac > > __driver_probe_device+0x78/0x12c > > driver_probe_device+0xdc/0x160 > > __device_attach_driver+0xb8/0x134 > > bus_for_each_drv+0x80/0xdc > > __device_attach+0xa8/0x1b0 > > device_initial_probe+0x14/0x20 > > bus_probe_device+0xa8/0xac > > deferred_probe_work_func+0x88/0xc0 > > process_one_work+0x138/0x260 > > worker_thread+0x32c/0x438 > > kthread+0x118/0x11c > > ret_from_fork+0x10/0x20 > > ---[ end trace 0000000000000000 ]--- > > > > Fix this by initializing directly the dmd pointer in dw_mipi_dsi_probe(), > > which requires also initializting the dmd->bridge attributes that are > > required in drm_bridge_attach() before calling mipi_dsi_host_register(). > > > > Signed-off-by: Farouk Bouabid > > --- > > drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c | 4 +- > > drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 42 ++++++++++--------- > > drivers/gpu/drm/meson/meson_dw_mipi_dsi.c | 8 ++-- > > .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 5 +-- > > drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 5 +-- > > include/drm/bridge/dw_mipi_dsi.h | 5 ++- > > 6 files changed, 35 insertions(+), 34 deletions(-) > > > > diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c > > index 3ff30ce80c5b..469976ad3b19 100644 > > --- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c > > +++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c > > @@ -881,8 +881,8 @@ static int imx93_dsi_probe(struct platform_device *pdev) > > dsi->pdata.priv_data = dsi; > > platform_set_drvdata(pdev, dsi); > > > > - dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata); > > - if (IS_ERR(dsi->dmd)) > > + ret = dw_mipi_dsi_probe(pdev, &dsi->pdata, &dsi->dmd); > > + if (ret < 0) > > return dev_err_probe(dev, PTR_ERR(dsi->dmd), > > "failed to probe dw_mipi_dsi\n"); > > > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c > > index 824fb3c65742..306cba366ba8 100644 > > --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c > > +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c > > @@ -1184,18 +1184,19 @@ static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) { } > > > > #endif /* CONFIG_DEBUG_FS */ > > > > -static struct dw_mipi_dsi * > > -__dw_mipi_dsi_probe(struct platform_device *pdev, > > - const struct dw_mipi_dsi_plat_data *plat_data) > > +int __dw_mipi_dsi_probe(struct platform_device *pdev, > > + const struct dw_mipi_dsi_plat_data *plat_data, struct dw_mipi_dsi **dsi_p) > > { > > struct device *dev = &pdev->dev; > > struct reset_control *apb_rst; > > struct dw_mipi_dsi *dsi; > > int ret; > > > > - dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); > > - if (!dsi) > > - return ERR_PTR(-ENOMEM); > > + *dsi_p = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); > > + if (!*dsi_p) > > + return -ENOMEM; > > + > > + dsi = *dsi_p; > > > > dsi->dev = dev; > > dsi->plat_data = plat_data; > > @@ -1203,13 +1204,13 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, > > if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps || > > !plat_data->phy_ops->get_timing) { > > DRM_ERROR("Phy not properly configured\n"); > > - return ERR_PTR(-ENODEV); > > + return -ENODEV; > > } > > > > if (!plat_data->base) { > > dsi->base = devm_platform_ioremap_resource(pdev, 0); > > if (IS_ERR(dsi->base)) > > - return ERR_PTR(-ENODEV); > > + return -ENODEV; > > > > } else { > > dsi->base = plat_data->base; > > @@ -1219,7 +1220,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, > > if (IS_ERR(dsi->pclk)) { > > ret = PTR_ERR(dsi->pclk); > > dev_err(dev, "Unable to get pclk: %d\n", ret); > > - return ERR_PTR(ret); > > + return ret; > > } > > > > /* > > @@ -1233,14 +1234,14 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, > > if (ret != -EPROBE_DEFER) > > dev_err(dev, "Unable to get reset control: %d\n", ret); > > > > - return ERR_PTR(ret); > > + return ret; > > } > > > > if (apb_rst) { > > ret = clk_prepare_enable(dsi->pclk); > > if (ret) { > > dev_err(dev, "%s: Failed to enable pclk\n", __func__); > > - return ERR_PTR(ret); > > + return ret; > > } > > > > reset_control_assert(apb_rst); > > @@ -1255,19 +1256,20 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, > > > > dsi->dsi_host.ops = &dw_mipi_dsi_host_ops; > > dsi->dsi_host.dev = dev; > > + dsi->bridge.driver_private = dsi; > > + dsi->bridge.funcs = &dw_mipi_dsi_bridge_funcs; > > + dsi->bridge.of_node = pdev->dev.of_node; > > + > > ret = mipi_dsi_host_register(&dsi->dsi_host); > > if (ret) { > > dev_err(dev, "Failed to register MIPI host: %d\n", ret); > > pm_runtime_disable(dev); > > dw_mipi_dsi_debugfs_remove(dsi); > > - return ERR_PTR(ret); > > + return ret; > > } > > > > - dsi->bridge.driver_private = dsi; > > - dsi->bridge.funcs = &dw_mipi_dsi_bridge_funcs; > > - dsi->bridge.of_node = pdev->dev.of_node; > > > > - return dsi; > > + return 0; > > } > > > > static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi) > > @@ -1301,11 +1303,11 @@ EXPORT_SYMBOL_GPL(dw_mipi_dsi_get_bridge); > > /* > > * Probe/remove API, used from platforms based on the DRM bridge API. > > */ > > -struct dw_mipi_dsi * > > -dw_mipi_dsi_probe(struct platform_device *pdev, > > - const struct dw_mipi_dsi_plat_data *plat_data) > > +int dw_mipi_dsi_probe(struct platform_device *pdev, > > + const struct dw_mipi_dsi_plat_data *plat_data, > > + struct dw_mipi_dsi **dsi_p) > > { > > - return __dw_mipi_dsi_probe(pdev, plat_data); > > + return __dw_mipi_dsi_probe(pdev, plat_data, dsi_p); > > } > > EXPORT_SYMBOL_GPL(dw_mipi_dsi_probe); > > > > diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c > > index e5fe4e994f43..b103f3e31f2a 100644 > > --- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c > > +++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c > > @@ -262,6 +262,7 @@ static int meson_dw_mipi_dsi_probe(struct platform_device *pdev) > > { > > struct meson_dw_mipi_dsi *mipi_dsi; > > struct device *dev = &pdev->dev; > > + int ret; > > > > mipi_dsi = devm_kzalloc(dev, sizeof(*mipi_dsi), GFP_KERNEL); > > if (!mipi_dsi) > > @@ -315,10 +316,9 @@ static int meson_dw_mipi_dsi_probe(struct platform_device *pdev) > > mipi_dsi->pdata.priv_data = mipi_dsi; > > platform_set_drvdata(pdev, mipi_dsi); > > > > - mipi_dsi->dmd = dw_mipi_dsi_probe(pdev, &mipi_dsi->pdata); > > - if (IS_ERR(mipi_dsi->dmd)) > > - return dev_err_probe(dev, PTR_ERR(mipi_dsi->dmd), > > - "Failed to probe dw_mipi_dsi\n"); > > + ret = dw_mipi_dsi_probe(pdev, &mipi_dsi->pdata, &mipi_dsi->dmd); > > + if (ret < 0) > > + return dev_err_probe(dev, ret, "Failed to probe dw_mipi_dsi\n"); > > > > return 0; > > } > > diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c > > index 6396f9324dab..4df32747476c 100644 > > --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c > > +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c > > @@ -1457,9 +1457,8 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) > > if (IS_ERR(phy_provider)) > > return PTR_ERR(phy_provider); > > > > - dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata); > > - if (IS_ERR(dsi->dmd)) { > > - ret = PTR_ERR(dsi->dmd); > > + ret = dw_mipi_dsi_probe(pdev, &dsi->pdata, &dsi->dmd); > > + if (ret < 0) { > > if (ret != -EPROBE_DEFER) > > DRM_DEV_ERROR(dev, > > "Failed to probe dw_mipi_dsi: %d\n", ret); > > diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c > > index d5f8c923d7bc..44dbbfc277d8 100644 > > --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c > > +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c > > @@ -518,9 +518,8 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) > > > > platform_set_drvdata(pdev, dsi); > > > > - dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data); > > - if (IS_ERR(dsi->dsi)) { > > - ret = PTR_ERR(dsi->dsi); > > + ret = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data, &dsi->dsi); > > + if (ret < 0) { > > dev_err_probe(dev, ret, "Failed to initialize mipi dsi host\n"); > > goto err_dsi_probe; > > } > > diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h > > index 65d5e68065e3..f073e819251e 100644 > > --- a/include/drm/bridge/dw_mipi_dsi.h > > +++ b/include/drm/bridge/dw_mipi_dsi.h > > @@ -76,9 +76,10 @@ struct dw_mipi_dsi_plat_data { > > void *priv_data; > > }; > > > > -struct dw_mipi_dsi *dw_mipi_dsi_probe(struct platform_device *pdev, > > +int dw_mipi_dsi_probe(struct platform_device *pdev, > > const struct dw_mipi_dsi_plat_data > > - *plat_data); > > + *plat_data, > > + struct dw_mipi_dsi **dsi_p); > > void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi); > > int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder); > > void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi); > >