From patchwork Tue May 27 12:42:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inki Dae X-Patchwork-Id: 4249111 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 89D369F32B for ; Tue, 27 May 2014 12:42:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5474B2026F for ; Tue, 27 May 2014 12:42:51 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 00F202017D for ; Tue, 27 May 2014 12:42:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 34F926E420; Tue, 27 May 2014 05:42:49 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 26E966E420 for ; Tue, 27 May 2014 05:42:46 -0700 (PDT) Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0N6800HG7GN95YA0@mailout1.samsung.com> for dri-devel@lists.freedesktop.org; Tue, 27 May 2014 21:42:45 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.113]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id 9E.66.24374.44884835; Tue, 27 May 2014 21:42:44 +0900 (KST) X-AuditID: cbfee68d-b7fd46d000005f36-8f-538488447449 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 71.DB.08203.44884835; Tue, 27 May 2014 21:42:44 +0900 (KST) Received: from daeinki-desktop.10.32.193.11 ([10.252.83.67]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0N680038CGN7F010@mmp1.samsung.com>; Tue, 27 May 2014 21:42:44 +0900 (KST) From: Inki Dae To: airlied@linux.ie, dri-devel@lists.freedesktop.org Subject: [PATCH 1/2] drm/exynos: consider deferred probe case Date: Tue, 27 May 2014 21:42:42 +0900 Message-id: <1401194563-803-2-git-send-email-inki.dae@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1401194563-803-1-git-send-email-inki.dae@samsung.com> References: <1401194563-803-1-git-send-email-inki.dae@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrILMWRmVeSWpSXmKPExsWyRsSkUNeloyXYoPOGjcWtdedYLXrPnWSy uPL1PZvFpPsTWCxmnN/HZLH5w0s2BzaPluYeNo/t3x6wetzvPs7k0bdlFaPH501yAaxRXDYp qTmZZalF+nYJXBm39xxmKTieX7Hs/QT2BsY5MV2MnBwSAiYSE/b9Z4awxSQu3FvP1sXIxSEk sJRR4mT3a1aYoi87rkMlFjFK7P/zmx3C6WaSOLV7GyNIFZuAqsTEFffZQGwRAVOJjklLWUBs ZoEqieub34HZwgK2EgeebmEHsVmA6qd2nAHbwCvgJLHw626mLkYOoG0KEnMm2YCEOQWcJRYs +A1WLgRUsubEIiaQvRICk9klzsw5zAwxR0Di2+RDLBC9shKbDkB9IylxcMUNlgmMwgsYGVYx iqYWJBcUJ6UXGeoVJ+YWl+al6yXn525iBAb36X/Pencw3j5gfYgxGWjcRGYp0eR8YHTklcQb GpsZWZiamBobmVuakSasJM6b9DApSEggPbEkNTs1tSC1KL6oNCe1+BAjEwenVAPjCvdvN7Qm ybmsUhZaWrOdjXHasyndfvGRUb6tDcFM++1m/6v79DPvzjfBMyX7p0iUKIQ+f+J9Tapn/sOD C3n87RQX8f4L2Cy/yLWNbV1FRd63CpbsulOrz7zfoMG6753ivCPi/46aLUw2Fd7Y2HB3R0G2 ptfN959yUy6/XNTwpitLzqt/StYLJZbijERDLeai4kQA1wxq7oQCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrHIsWRmVeSWpSXmKPExsVy+t9jAV2XjpZgg2NnDCxurTvHatF77iST xZWv79ksJt2fwGIx4/w+JovNH16yObB5tDT3sHls//aA1eN+93Emj74tqxg9Pm+SC2CNamC0 yUhNTEktUkjNS85PycxLt1XyDo53jjc1MzDUNbS0MFdSyEvMTbVVcvEJ0HXLzAE6QUmhLDGn FCgUkFhcrKRvh2lCaIibrgVMY4Sub0gQXI+RARpIWMOYcXvPYZaC4/kVy95PYG9gnBPTxcjJ ISFgIvFlx3U2CFtM4sK99UA2F4eQwCJGif1/frNDON1MEqd2b2MEqWITUJWYuOI+WIeIgKlE x6SlLCA2s0CVxPXN78BsYQFbiQNPt7CD2CxA9VM7zrCC2LwCThILv+5m6mLkANqmIDFnkg1I mFPAWWLBgt9g5UJAJWtOLGKawMi7gJFhFaNoakFyQXFSeq6hXnFibnFpXrpecn7uJkZw7DyT 2sG4ssHiEKMAB6MSD+8E3+ZgIdbEsuLK3EOMEhzMSiK8ZW0twUK8KYmVValF+fFFpTmpxYcY k4GOmsgsJZqcD4zrvJJ4Q2MTMyNLI3NDCyNjc9KElcR5D7RaBwoJpCeWpGanphakFsFsYeLg lGpg1DqWpdndF/3V4cw5lpSqFSopG5d90KuTyvD49vnxxUZG09bZ2c2MjCym1ums68/llvev ZZu7wqj3heLP6w1SlhNfSpiWl/j+4tJYfMDk1PSvrQs1FX8VvRDtFeQu/ZYYX2by68F3xhlp k6xCv5btiOlQEj1i8uplmufslCPe+YJxV/g7N2YpsRRnJBpqMRcVJwIAsIeHOuECAAA= DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Cc: a.hajda@samsung.com, linux-samsung-soc@vger.kernel.org, rmk+kernel@arm.linux.org.uk X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch makes sure that exynos drm framework handles deferred probe case correctly. Sub drivers could be probed before resources, clock, regulator, phy or panel, are ready for them so we should make sure that exynos drm core waits until all resources are ready and sub drivers are probed correctly. Signed-off-by: Inki Dae Acked-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_dp_core.c | 16 +++++++- drivers/gpu/drm/exynos/exynos_drm_drv.c | 28 +++++++------- drivers/gpu/drm/exynos/exynos_drm_drv.h | 7 +--- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 31 +++++++++++---- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 49 +++++++++++++++++------ drivers/gpu/drm/exynos/exynos_hdmi.c | 62 ++++++++++++++++++++++-------- drivers/gpu/drm/exynos/exynos_mixer.c | 16 +++++++- 7 files changed, 151 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index ff63901..7526f36 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -1328,12 +1328,24 @@ static const struct component_ops exynos_dp_ops = { static int exynos_dp_probe(struct platform_device *pdev) { - return exynos_drm_component_add(&pdev->dev, &exynos_dp_ops); + int ret; + + ret = exynos_drm_component_add(&pdev->dev); + if (ret) + return ret; + + ret = component_add(&pdev->dev, &exynos_dp_ops); + if (ret) + exynos_drm_component_del(&pdev->dev); + + return ret; } static int exynos_dp_remove(struct platform_device *pdev) { - exynos_drm_component_del(&pdev->dev, &exynos_dp_ops); + component_del(&pdev->dev, &exynos_dp_ops); + exynos_drm_component_del(&pdev->dev); + return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index c5a401ae..f611f5a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -381,22 +381,25 @@ static const struct dev_pm_ops exynos_drm_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(exynos_drm_sys_suspend, exynos_drm_sys_resume) }; -int exynos_drm_component_add(struct device *dev, - const struct component_ops *ops) +int exynos_drm_component_add(struct device *dev) { struct component_dev *cdev; - int ret; + + mutex_lock(&drm_component_lock); + + list_for_each_entry(cdev, &drm_component_list, list) { + if (cdev->dev == dev) { + mutex_unlock(&drm_component_lock); + return 0; + } + } + + mutex_unlock(&drm_component_lock); cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) return -ENOMEM; - ret = component_add(dev, ops); - if (ret) { - kfree(cdev); - return ret; - } - cdev->dev = dev; mutex_lock(&drm_component_lock); @@ -406,8 +409,7 @@ int exynos_drm_component_add(struct device *dev, return 0; } -void exynos_drm_component_del(struct device *dev, - const struct component_ops *ops) +void exynos_drm_component_del(struct device *dev) { struct component_dev *cdev, *next; @@ -422,8 +424,6 @@ void exynos_drm_component_del(struct device *dev, } mutex_unlock(&drm_component_lock); - - component_del(dev, ops); } static int compare_of(struct device *dev, void *data) @@ -446,6 +446,8 @@ static int exynos_drm_add_components(struct device *dev, struct master *m) ret = component_master_add_child(m, compare_of, cdev->dev); if (!ret) attached_cnt++; + else + return ret; mutex_lock(&drm_component_lock); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index e82e620..13480b2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -354,12 +354,9 @@ void exynos_drm_remove_vidi(void); int exynos_drm_create_enc_conn(struct drm_device *dev, struct exynos_drm_display *display); -struct component_ops; -int exynos_drm_component_add(struct device *dev, - const struct component_ops *ops); +int exynos_drm_component_add(struct device *dev); -void exynos_drm_component_del(struct device *dev, - const struct component_ops *ops); +void exynos_drm_component_del(struct device *dev); extern struct platform_driver fimd_driver; extern struct platform_driver dp_driver; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 84661fe..1421d9b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1423,10 +1423,15 @@ static int exynos_dsi_probe(struct platform_device *pdev) struct exynos_dsi *dsi; int ret; + ret = exynos_drm_component_add(&pdev->dev); + if (ret) + return ret; + dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); if (!dsi) { dev_err(&pdev->dev, "failed to allocate dsi object.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_del_component; } init_completion(&dsi->completed); @@ -1440,7 +1445,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) ret = exynos_dsi_parse_dt(dsi); if (ret) - return ret; + goto err_del_component; dsi->supplies[0].supply = "vddcore"; dsi->supplies[1].supply = "vddio"; @@ -1467,7 +1472,8 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(dsi->reg_base)) { dev_err(&pdev->dev, "failed to remap io region\n"); - return PTR_ERR(dsi->reg_base); + ret = PTR_ERR(dsi->reg_base); + goto err_del_component; } dsi->phy = devm_phy_get(&pdev->dev, "dsim"); @@ -1479,7 +1485,8 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->irq = platform_get_irq(pdev, 0); if (dsi->irq < 0) { dev_err(&pdev->dev, "failed to request dsi irq resource\n"); - return dsi->irq; + ret = dsi->irq; + goto err_del_component; } irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN); @@ -1488,19 +1495,29 @@ static int exynos_dsi_probe(struct platform_device *pdev) dev_name(&pdev->dev), dsi); if (ret) { dev_err(&pdev->dev, "failed to request dsi irq\n"); - return ret; + goto err_del_component; } exynos_dsi_display.ctx = dsi; platform_set_drvdata(pdev, &exynos_dsi_display); - return exynos_drm_component_add(&pdev->dev, &exynos_dsi_component_ops); + ret = component_add(&pdev->dev, &exynos_dsi_component_ops); + if (ret) + goto err_del_component; + + return ret; + +err_del_component: + exynos_drm_component_del(&pdev->dev); + return ret; } static int exynos_dsi_remove(struct platform_device *pdev) { - exynos_drm_component_del(&pdev->dev, &exynos_dsi_component_ops); + component_del(&pdev->dev, &exynos_dsi_component_ops); + exynos_drm_component_del(&pdev->dev); + return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index bd30d0c..5b85253 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -941,12 +941,21 @@ static int fimd_probe(struct platform_device *pdev) struct resource *res; int ret = -EINVAL; - if (!dev->of_node) - return -ENODEV; + + ret = exynos_drm_component_add(&pdev->dev); + if (ret) + return ret; + + if (!dev->of_node) { + ret = -ENODEV; + goto err_del_component; + } ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + if (!ctx) { + ret = -ENOMEM; + goto err_del_component; + } ctx->dev = dev; ctx->suspended = true; @@ -959,32 +968,35 @@ static int fimd_probe(struct platform_device *pdev) ctx->bus_clk = devm_clk_get(dev, "fimd"); if (IS_ERR(ctx->bus_clk)) { dev_err(dev, "failed to get bus clock\n"); - return PTR_ERR(ctx->bus_clk); + return -EPROBE_DEFER; } ctx->lcd_clk = devm_clk_get(dev, "sclk_fimd"); if (IS_ERR(ctx->lcd_clk)) { dev_err(dev, "failed to get lcd clock\n"); - return PTR_ERR(ctx->lcd_clk); + return -EPROBE_DEFER; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ctx->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(ctx->regs)) - return PTR_ERR(ctx->regs); + if (IS_ERR(ctx->regs)) { + ret = PTR_ERR(ctx->regs); + goto err_del_component; + } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync"); if (!res) { dev_err(dev, "irq request failed.\n"); - return -ENXIO; + ret = -ENXIO; + goto err_del_component; } ret = devm_request_irq(dev, res->start, fimd_irq_handler, 0, "drm_fimd", ctx); if (ret) { dev_err(dev, "irq request failed.\n"); - return ret; + goto err_del_component; } ctx->driver_data = drm_fimd_get_driver_data(pdev); @@ -1001,14 +1013,27 @@ static int fimd_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - return exynos_drm_component_add(&pdev->dev, &fimd_component_ops); + ret = component_add(&pdev->dev, &fimd_component_ops); + if (ret) + goto err_disable_pm_runtime; + + return ret; + +err_disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + +err_del_component: + exynos_drm_component_del(&pdev->dev); + return ret; } static int fimd_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - exynos_drm_component_del(&pdev->dev, &fimd_component_ops); + component_del(&pdev->dev, &fimd_component_ops); + exynos_drm_component_del(&pdev->dev); + return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index e05c86a..5919800 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2275,24 +2275,36 @@ static int hdmi_probe(struct platform_device *pdev) struct resource *res; int ret; - if (!dev->of_node) - return -ENODEV; + ret = exynos_drm_component_add(&pdev->dev); + if (ret) + return ret; + + if (!dev->of_node) { + ret = -ENODEV; + goto err_del_component; + } pdata = drm_hdmi_dt_parse_pdata(dev); - if (!pdata) - return -EINVAL; + if (!pdata) { + ret = -EINVAL; + goto err_del_component; + } hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); - if (!hdata) - return -ENOMEM; + if (!hdata) { + ret = -ENOMEM; + goto err_del_component; + } mutex_init(&hdata->hdmi_mutex); platform_set_drvdata(pdev, &hdmi_display); match = of_match_node(hdmi_match_types, dev->of_node); - if (!match) - return -ENODEV; + if (!match) { + ret = -ENODEV; + goto err_del_component; + } drv_data = (struct hdmi_driver_data *)match->data; hdata->type = drv_data->type; @@ -2305,18 +2317,20 @@ static int hdmi_probe(struct platform_device *pdev) ret = hdmi_resources_init(hdata); if (ret) { DRM_ERROR("hdmi_resources_init failed\n"); - return -EINVAL; + return -EPROBE_DEFER; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hdata->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(hdata->regs)) - return PTR_ERR(hdata->regs); + if (IS_ERR(hdata->regs)) { + ret = PTR_ERR(hdata->regs); + goto err_del_component; + } ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD"); if (ret) { DRM_ERROR("failed to request HPD gpio\n"); - return ret; + goto err_del_component; } ddc_node = hdmi_legacy_ddc_dt_binding(dev); @@ -2327,14 +2341,15 @@ static int hdmi_probe(struct platform_device *pdev) ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); if (!ddc_node) { DRM_ERROR("Failed to find ddc node in device tree\n"); - return -ENODEV; + ret = -ENODEV; + goto err_del_component; } out_get_ddc_adpt: hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node); if (!hdata->ddc_adpt) { DRM_ERROR("Failed to get ddc i2c adapter by node\n"); - return -ENODEV; + return -EPROBE_DEFER; } phy_node = hdmi_legacy_phy_dt_binding(dev); @@ -2361,7 +2376,7 @@ out_get_phy_port: hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node); if (!hdata->hdmiphy_port) { DRM_ERROR("Failed to get hdmi phy i2c client\n"); - ret = -ENODEV; + ret = -EPROBE_DEFER; goto err_ddc; } } @@ -2390,19 +2405,31 @@ out_get_phy_port: "samsung,syscon-phandle"); if (IS_ERR(hdata->pmureg)) { DRM_ERROR("syscon regmap lookup failed.\n"); + ret = -EPROBE_DEFER; goto err_hdmiphy; } pm_runtime_enable(dev); hdmi_display.ctx = hdata; - return exynos_drm_component_add(&pdev->dev, &hdmi_component_ops); + ret = component_add(&pdev->dev, &hdmi_component_ops); + if (ret) + goto err_disable_pm_runtime; + + return ret; + +err_disable_pm_runtime: + pm_runtime_disable(dev); err_hdmiphy: if (hdata->hdmiphy_port) put_device(&hdata->hdmiphy_port->dev); err_ddc: put_device(&hdata->ddc_adpt->dev); + +err_del_component: + exynos_drm_component_del(&pdev->dev); + return ret; } @@ -2416,8 +2443,9 @@ static int hdmi_remove(struct platform_device *pdev) put_device(&hdata->ddc_adpt->dev); pm_runtime_disable(&pdev->dev); + component_del(&pdev->dev, &hdmi_component_ops); - exynos_drm_component_del(&pdev->dev, &hdmi_component_ops); + exynos_drm_component_del(&pdev->dev); return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 483d7c0..eaae17b 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1273,12 +1273,24 @@ static const struct component_ops mixer_component_ops = { static int mixer_probe(struct platform_device *pdev) { - return exynos_drm_component_add(&pdev->dev, &mixer_component_ops); + int ret; + + ret = exynos_drm_component_add(&pdev->dev); + if (ret) + return ret; + + ret = component_add(&pdev->dev, &mixer_component_ops); + if (ret) + exynos_drm_component_del(&pdev->dev); + + return ret; } static int mixer_remove(struct platform_device *pdev) { - exynos_drm_component_del(&pdev->dev, &mixer_component_ops); + component_del(&pdev->dev, &mixer_component_ops); + exynos_drm_component_del(&pdev->dev); + return 0; }