From patchwork Wed Dec 1 10:52:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AngeloGioacchino Del Regno X-Patchwork-Id: 519888 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9C627C433EF for ; Wed, 1 Dec 2021 10:52:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229793AbhLAKzl (ORCPT ); Wed, 1 Dec 2021 05:55:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242505AbhLAKzk (ORCPT ); Wed, 1 Dec 2021 05:55:40 -0500 Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F22F5C061574; Wed, 1 Dec 2021 02:52:19 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: kholk11) with ESMTPSA id 06D9D1F45630 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=collabora.com; s=mail; t=1638355938; bh=rL9Yo0VP8rvWWbfN9374jnoFbEFvxR/1usMNsyxgNhg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GhOvmzRBH6ydmh3oDb3Ju4hTU4S7ptZWIgytadzTT3xEd1H438JXLGqOQVMRr5Lw6 NOHiJO9s7S1tI6fWuRt24Ue8mbPAuRCpmN6rVxu/znMNrG1rvrGoa8wAyl66Bi9eo+ lypT5RYbnoxyNjGG4a+ieSyBzCIu9GN76OtKWc3kt+LABz/ZnpuFpAHrifJoDgdE7z s0NbFq373f6jwQ2+d3gNuYuAtHCgP4X5YyRC4re3w5Dnvt56RB7w7VNoXaFraXZB07 vMBa9KhYI2So5VKuY7pWzm0QOQGP1XCUb9JhYeJv/UdMEs+zU6H/9lh25JdsQAkS8J CjHKA7xxSODAA== From: AngeloGioacchino Del Regno To: robdclark@gmail.com Cc: dmitry.baryshkov@linaro.org, sean@poorly.run, airlied@linux.ie, daniel@ffwll.ch, maxime@cerno.tech, linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org, kernel@collabora.com, konrad.dybcio@somainline.org, marijn.suijten@somainline.org, jami.kettunen@somainline.org, martin.botka@somainline.org, AngeloGioacchino Del Regno Subject: [PATCH v3 2/2] drm/msm: Initialize MDSS irq domain at probe time Date: Wed, 1 Dec 2021 11:52:10 +0100 Message-Id: <20211201105210.24970-3-angelogioacchino.delregno@collabora.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201105210.24970-1-angelogioacchino.delregno@collabora.com> References: <20211201105210.24970-1-angelogioacchino.delregno@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Since commit 8f59ee9a570c ("drm/msm/dsi: Adjust probe order"), the DSI host gets initialized earlier, but this caused unability to probe the entire stack of components because they all depend on interrupts coming from the main `mdss` node (mdp5, or dpu1). To fix this issue, anticipate registering the irq domain from mdp5/dpu1 at msm_mdev_probe() time, as to make sure that the interrupt controller is available before dsi and/or other components try to initialize, finally satisfying the dependency. Moreover, to balance this operation while avoiding to always check if the irq domain is registered everytime we call bind() on msm_pdev, add a new *remove function pointer to msm_mdss_funcs, used to remove the irq domain only at msm_pdev_remove() time. Fixes: 8f59ee9a570c ("drm/msm/dsi: Adjust probe order") Signed-off-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 50 ++++++++++++------- drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c | 58 +++++++++++++++-------- drivers/gpu/drm/msm/msm_drv.c | 22 ++++++++- drivers/gpu/drm/msm/msm_kms.h | 3 ++ 4 files changed, 95 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index b466784d9822..6c2569175633 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -106,13 +106,10 @@ static const struct irq_domain_ops dpu_mdss_irqdomain_ops = { .xlate = irq_domain_xlate_onecell, }; -static int _dpu_mdss_irq_domain_add(struct dpu_mdss *dpu_mdss) +static int _dpu_mdss_irq_domain_add(struct device *dev, struct dpu_mdss *dpu_mdss) { - struct device *dev; struct irq_domain *domain; - dev = dpu_mdss->base.dev->dev; - domain = irq_domain_add_linear(dev->of_node, 32, &dpu_mdss_irqdomain_ops, dpu_mdss); if (!domain) { @@ -194,7 +191,6 @@ static void dpu_mdss_destroy(struct drm_device *dev) pm_runtime_suspend(dev->dev); pm_runtime_disable(dev->dev); - _dpu_mdss_irq_domain_fini(dpu_mdss); irq = platform_get_irq(pdev, 0); irq_set_chained_handler_and_data(irq, NULL, NULL); msm_dss_put_clk(mp->clk_config, mp->num_clk); @@ -203,15 +199,43 @@ static void dpu_mdss_destroy(struct drm_device *dev) if (dpu_mdss->mmio) devm_iounmap(&pdev->dev, dpu_mdss->mmio); dpu_mdss->mmio = NULL; - priv->mdss = NULL; +} + +static void dpu_mdss_remove(struct msm_mdss *mdss) +{ + _dpu_mdss_irq_domain_fini(to_dpu_mdss(mdss)); } static const struct msm_mdss_funcs mdss_funcs = { .enable = dpu_mdss_enable, .disable = dpu_mdss_disable, .destroy = dpu_mdss_destroy, + .remove = dpu_mdss_remove, }; +int dpu_mdss_early_init(struct device *dev, struct msm_drm_private *priv) +{ + struct dpu_mdss *dpu_mdss; + int ret; + + dpu_mdss = devm_kzalloc(dev, sizeof(*dpu_mdss), GFP_KERNEL); + if (!dpu_mdss) + return -ENOMEM; + + ret = _dpu_mdss_irq_domain_add(dev, dpu_mdss); + if (ret) + return ret; + + /* + * Here we have no drm_device yet, but still do the assignment + * so that we can retrieve our struct dpu_mdss from the main + * init function, since we allocate it here. + */ + priv->mdss = &dpu_mdss->base; + + return 0; +} + int dpu_mdss_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); @@ -221,9 +245,9 @@ int dpu_mdss_init(struct drm_device *dev) int ret; int irq; - dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL); + dpu_mdss = to_dpu_mdss(priv->mdss); if (!dpu_mdss) - return -ENOMEM; + return -ENODATA; dpu_mdss->mmio = msm_ioremap(pdev, "mdss", "mdss"); if (IS_ERR(dpu_mdss->mmio)) @@ -241,10 +265,6 @@ int dpu_mdss_init(struct drm_device *dev) dpu_mdss->base.dev = dev; dpu_mdss->base.funcs = &mdss_funcs; - ret = _dpu_mdss_irq_domain_add(dpu_mdss); - if (ret) - goto irq_domain_error; - irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; @@ -253,16 +273,10 @@ int dpu_mdss_init(struct drm_device *dev) irq_set_chained_handler_and_data(irq, dpu_mdss_irq, dpu_mdss); - - priv->mdss = &dpu_mdss->base; - pm_runtime_enable(dev->dev); - return 0; irq_error: - _dpu_mdss_irq_domain_fini(dpu_mdss); -irq_domain_error: msm_dss_put_clk(mp->clk_config, mp->num_clk); clk_parse_err: devm_kfree(&pdev->dev, mp->clk_config); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c index 0ea53420bc40..a99538ae4182 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c @@ -112,9 +112,8 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = { }; -static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss) +static int mdss_irq_domain_init(struct device *dev, struct mdp5_mdss *mdp5_mdss) { - struct device *dev = mdp5_mdss->base.dev->dev; struct irq_domain *d; d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops, @@ -182,20 +181,52 @@ static void mdp5_mdss_destroy(struct drm_device *dev) if (!mdp5_mdss) return; - irq_domain_remove(mdp5_mdss->irqcontroller.domain); - mdp5_mdss->irqcontroller.domain = NULL; - regulator_disable(mdp5_mdss->vdd); pm_runtime_disable(dev->dev); } +static void mdp5_mdss_remove(struct msm_mdss *mdss) +{ + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); + + irq_domain_remove(mdp5_mdss->irqcontroller.domain); + mdp5_mdss->irqcontroller.domain = NULL; +} + static const struct msm_mdss_funcs mdss_funcs = { .enable = mdp5_mdss_enable, .disable = mdp5_mdss_disable, .destroy = mdp5_mdss_destroy, + .remove = mdp5_mdss_remove, }; +int mdp5_mdss_early_init(struct device *dev, struct msm_drm_private *priv) +{ + struct mdp5_mdss *mdp5_mdss; + int ret; + + if (!of_device_is_compatible(dev->of_node, "qcom,mdss")) + return 0; + + mdp5_mdss = devm_kzalloc(dev, sizeof(*mdp5_mdss), GFP_KERNEL); + if (!mdp5_mdss) + return -ENOMEM; + + ret = mdss_irq_domain_init(dev, mdp5_mdss); + if (ret) + return ret; + + /* + * Here we have no drm_device yet, but still do the assignment + * so that we can retrieve our struct mdp5_mdss from the main + * init function, since we allocate it here. + */ + priv->mdss = &mdp5_mdss->base; + + return 0; +} + int mdp5_mdss_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); @@ -208,11 +239,9 @@ int mdp5_mdss_init(struct drm_device *dev) if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) return 0; - mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL); - if (!mdp5_mdss) { - ret = -ENOMEM; - goto fail; - } + mdp5_mdss = to_mdp5_mdss(priv->mdss); + if (!mdp5_mdss) + return -ENODATA; mdp5_mdss->base.dev = dev; @@ -255,17 +284,8 @@ int mdp5_mdss_init(struct drm_device *dev) goto fail_irq; } - ret = mdss_irq_domain_init(mdp5_mdss); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to init sub-block irqs: %d\n", ret); - goto fail_irq; - } - mdp5_mdss->base.funcs = &mdss_funcs; - priv->mdss = &mdp5_mdss->base; - pm_runtime_enable(dev->dev); - return 0; fail_irq: regulator_disable(mdp5_mdss->vdd); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 64230e473a34..ded4f4d6545f 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1389,6 +1389,20 @@ static int msm_pdev_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + switch (get_mdp_ver(pdev)) { + case KMS_MDP5: + ret = mdp5_mdss_early_init(&pdev->dev, priv); + break; + case KMS_DPU: + ret = dpu_mdss_early_init(&pdev->dev, priv); + break; + default: + ret = 0; + break; + } + if (ret) + return ret; + platform_set_drvdata(pdev, priv); if (get_mdp_ver(pdev)) { @@ -1421,6 +1435,12 @@ static int msm_pdev_probe(struct platform_device *pdev) static int msm_pdev_remove(struct platform_device *pdev) { + struct msm_drm_private *priv = platform_get_drvdata(pdev); + + if (priv->mdss && priv->mdss->funcs) + priv->mdss->funcs->remove(priv->mdss); + + priv->mdss = NULL; component_master_del(&pdev->dev, &msm_drm_ops); of_platform_depopulate(&pdev->dev); @@ -1432,7 +1452,7 @@ static void msm_pdev_shutdown(struct platform_device *pdev) struct msm_drm_private *priv = platform_get_drvdata(pdev); struct drm_device *drm = priv ? priv->dev : NULL; - if (!priv || !priv->kms) + if (!priv || !priv->kms || !drm->mode_config.funcs) return; drm_atomic_helper_shutdown(drm); diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 6a42b819abc4..2c539a228156 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -202,6 +202,7 @@ struct msm_mdss_funcs { int (*enable)(struct msm_mdss *mdss); int (*disable)(struct msm_mdss *mdss); void (*destroy)(struct drm_device *dev); + void (*remove)(struct msm_mdss *mdss); }; struct msm_mdss { @@ -209,7 +210,9 @@ struct msm_mdss { const struct msm_mdss_funcs *funcs; }; +int mdp5_mdss_early_init(struct device *dev, struct msm_drm_private *priv); int mdp5_mdss_init(struct drm_device *dev); +int dpu_mdss_early_init(struct device *dev, struct msm_drm_private *priv); int dpu_mdss_init(struct drm_device *dev); #define for_each_crtc_mask(dev, crtc, crtc_mask) \