Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2279693imm; Mon, 28 May 2018 05:17:34 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpPbOnP1uCd2C2Mlp7JYMVrR8FJxYkQFGaNjiFkuCyIVPQsVQvXpAUCmqNRiXjT8t69HzDk X-Received: by 2002:a65:5c09:: with SMTP id u9-v6mr10477438pgr.304.1527509854785; Mon, 28 May 2018 05:17:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527509854; cv=none; d=google.com; s=arc-20160816; b=XG+ppaioTM8zCi2g7RXeIxqXQVTxRn2G+6g2NbO/3nksl/d1bIY0XwkeBOd8iAa+ZO c9bsb6uS/OsNcKip/59nfK1XBoGFAcVeW3Do5kvIpASwIv/AoYVS+TsSiYfkz6bohV3K /caV6w41VLcZQsYj1CK+AO2plCjmmmLsiWqoEK2+gus32faXN1vek/253yeNDHDd5f/8 kEMNIeVB7malfVNXHk/HR9N3jG8FrVV+7B9VvbU/Hf98BmnUfW8AoAbTqcfS/tSr/LOd 5TOtMJGHIezFqozDYj5TzMVlPkEzGXq2pqa3QVUHY2PwNk+fnvEbpvkDVHigctUQpVHx xPKA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=XtQCj0Nfu0E2F0E4bki+Dr3iYatXLP7vY8sunOvgssg=; b=p1a1Ma98yHUW3qCkbsscYrXA1SbUebwr7ypr/z3fqCaMD2Q5NSMnxi2JlUfS7e9M6N AweU1OWeSrkWU1lG8XeJuSWhzx/6VlV3HhwXJsDQR87qV1BGiQDwtCrPU+JxmMocdv8K 3yRxhS1bYfXgM8arji52N2qhi8yF7cMW7oL9Cl78GY2pJqKdKeoToA+iW5yB8zt6HV9D gWF/swwh6LYErBOk9YwJfmZTfM0e/BdsQGNaka/qJ+4T2CeWmAKb/u9NAGHMkG4R2DHc BzvWDHON9+wxYcYxnldWH8wfHVvb3pnOjtR0BskE3nRDUb/QGC/7CiVQoae6R/CSmdIe OjaQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=THuYr5zG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v5-v6si30415952plo.166.2018.05.28.05.17.19; Mon, 28 May 2018 05:17:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=THuYr5zG; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1423418AbeE1MQm (ORCPT + 99 others); Mon, 28 May 2018 08:16:42 -0400 Received: from mail.kernel.org ([198.145.29.99]:50456 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1422910AbeE1LDL (ORCPT ); Mon, 28 May 2018 07:03:11 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DEBDE20883; Mon, 28 May 2018 11:03:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1527505391; bh=fx9iV0ESDPQEMB54wjrTkpYDU+pQwDqvwO1qGrSp5ec=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=THuYr5zGaHFLQjwhlddW2VYAEgP+kZiF4zH+RpWcGWCK99UTEOTP910xfdZn519sq zUlbrq+LEpr0VRvvS2vTDrnHeDupF+2q5cQZgFdRXKhu3o29OSfq0jJKvEpb0he0gH 1IpgHoYaRg2/UJ1bVAvDl2jsJRyrb8oR/7UeoWaI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Laurent Pinchart , Sebastian Reichel , Tomi Valkeinen , Sasha Levin Subject: [PATCH 4.14 454/496] drm: omapdrm: dss: Move initialization code from component bind to probe Date: Mon, 28 May 2018 12:03:59 +0200 Message-Id: <20180528100339.038756658@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180528100319.498712256@linuxfoundation.org> References: <20180528100319.498712256@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Laurent Pinchart [ Upstream commit 215003b4ae1d47035092fef73b6a22aa82037091 ] There's no reason to delay initialization of most of the driver (such as mapping memory I/O, getting clocks or enabling runtime PM) to the component master bind handler. This additionally fixes a real PM issue caused enabling runtime PM in the bind handler. The bind handler performs the following sequence of PM operations: pm_runtime_enable(dev); pm_runtime_get_sync(dev); ... (access the hardware to read the device revision) ... pm_runtime_put_sync(dev); If a failure occurs at this point, the error path calls pm_runtime_disable() to balance the pm_runtime_enable() call. To understand the problem, it should be noted that the bind handler is called when one of the component registers itself, which happens in the component's probe handler. Furthermore, as the components are children of the DSS, the device core calls pm_runtime_get_sync() on the DSS platform device before calling the component's probe handler. This increases the DSS power usage count but doesn't runtime resume the device, as runtime PM is disabled at that point. The bind handler is thus called with runtime PM disabled, with the device runtime suspended, but with the power usage count larger than 0. The pm_runtime_get_sync() call will thus further increase the power usage count and runtime resume the device. The pm_runtime_put_sync() handler will decrease the power usage count to a non-zero value and will thus not suspend the device. Finally, the pm_runtime_disable() call will disable runtime PM, preventing the pm_runtime_put() call in the device core from runtime suspending the device. The DSS device is thus left powered on. To fix this, move the initialization code from the bind handler to the probe handler. Signed-off-by: Laurent Pinchart Reviewed-by: Sebastian Reichel Signed-off-by: Tomi Valkeinen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/omapdrm/dss/dss.c | 193 ++++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 89 deletions(-) --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1299,88 +1299,18 @@ static const struct soc_device_attribute static int dss_bind(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct resource *dss_mem; - u32 rev; int r; - dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); - dss.base = devm_ioremap_resource(&pdev->dev, dss_mem); - if (IS_ERR(dss.base)) - return PTR_ERR(dss.base); - - r = dss_get_clocks(); + r = component_bind_all(dev, NULL); if (r) return r; - r = dss_setup_default_clock(); - if (r) - goto err_setup_clocks; - - r = dss_video_pll_probe(pdev); - if (r) - goto err_pll_init; - - r = dss_init_ports(pdev); - if (r) - goto err_init_ports; - - pm_runtime_enable(&pdev->dev); - - r = dss_runtime_get(); - if (r) - goto err_runtime_get; - - dss.dss_clk_rate = clk_get_rate(dss.dss_clk); - - /* Select DPLL */ - REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); - - dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); - -#ifdef CONFIG_OMAP2_DSS_VENC - REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ - REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ - REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ -#endif - dss.dsi_clk_source[0] = DSS_CLK_SRC_FCK; - dss.dsi_clk_source[1] = DSS_CLK_SRC_FCK; - dss.dispc_clk_source = DSS_CLK_SRC_FCK; - dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; - dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; - - rev = dss_read_reg(DSS_REVISION); - pr_info("OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - dss_runtime_put(); - - r = component_bind_all(&pdev->dev, NULL); - if (r) - goto err_component; - - dss_debugfs_create_file("dss", dss_dump_regs); - pm_set_vt_switch(0); omapdss_gather_components(dev); omapdss_set_is_initialized(true); return 0; - -err_component: -err_runtime_get: - pm_runtime_disable(&pdev->dev); - dss_uninit_ports(pdev); -err_init_ports: - if (dss.video1_pll) - dss_video_pll_uninit(dss.video1_pll); - - if (dss.video2_pll) - dss_video_pll_uninit(dss.video2_pll); -err_pll_init: -err_setup_clocks: - dss_put_clocks(); - return r; } static void dss_unbind(struct device *dev) @@ -1390,18 +1320,6 @@ static void dss_unbind(struct device *de omapdss_set_is_initialized(false); component_unbind_all(&pdev->dev, NULL); - - if (dss.video1_pll) - dss_video_pll_uninit(dss.video1_pll); - - if (dss.video2_pll) - dss_video_pll_uninit(dss.video2_pll); - - dss_uninit_ports(pdev); - - pm_runtime_disable(&pdev->dev); - - dss_put_clocks(); } static const struct component_master_ops dss_component_ops = { @@ -1433,10 +1351,46 @@ static int dss_add_child_component(struc return 0; } +static int dss_probe_hardware(void) +{ + u32 rev; + int r; + + r = dss_runtime_get(); + if (r) + return r; + + dss.dss_clk_rate = clk_get_rate(dss.dss_clk); + + /* Select DPLL */ + REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); + + dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); + +#ifdef CONFIG_OMAP2_DSS_VENC + REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ + REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ + REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ +#endif + dss.dsi_clk_source[0] = DSS_CLK_SRC_FCK; + dss.dsi_clk_source[1] = DSS_CLK_SRC_FCK; + dss.dispc_clk_source = DSS_CLK_SRC_FCK; + dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; + dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; + + rev = dss_read_reg(DSS_REVISION); + pr_info("OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + + dss_runtime_put(); + + return 0; +} + static int dss_probe(struct platform_device *pdev) { const struct soc_device_attribute *soc; struct component_match *match = NULL; + struct resource *dss_mem; int r; dss.pdev = pdev; @@ -1451,20 +1405,69 @@ static int dss_probe(struct platform_dev else dss.feat = of_match_device(dss_of_match, &pdev->dev)->data; - r = dss_initialize_debugfs(); + /* Map I/O registers, get and setup clocks. */ + dss_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dss.base = devm_ioremap_resource(&pdev->dev, dss_mem); + if (IS_ERR(dss.base)) + return PTR_ERR(dss.base); + + r = dss_get_clocks(); if (r) return r; - /* add all the child devices as components */ + r = dss_setup_default_clock(); + if (r) + goto err_put_clocks; + + /* Setup the video PLLs and the DPI and SDI ports. */ + r = dss_video_pll_probe(pdev); + if (r) + goto err_put_clocks; + + r = dss_init_ports(pdev); + if (r) + goto err_uninit_plls; + + /* Enable runtime PM and probe the hardware. */ + pm_runtime_enable(&pdev->dev); + + r = dss_probe_hardware(); + if (r) + goto err_pm_runtime_disable; + + /* Initialize debugfs. */ + r = dss_initialize_debugfs(); + if (r) + goto err_pm_runtime_disable; + + dss_debugfs_create_file("dss", dss_dump_regs); + + /* Add all the child devices as components. */ device_for_each_child(&pdev->dev, &match, dss_add_child_component); r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match); - if (r) { - dss_uninitialize_debugfs(); - return r; - } + if (r) + goto err_uninit_debugfs; return 0; + +err_uninit_debugfs: + dss_uninitialize_debugfs(); + +err_pm_runtime_disable: + pm_runtime_disable(&pdev->dev); + dss_uninit_ports(pdev); + +err_uninit_plls: + if (dss.video1_pll) + dss_video_pll_uninit(dss.video1_pll); + if (dss.video2_pll) + dss_video_pll_uninit(dss.video2_pll); + +err_put_clocks: + dss_put_clocks(); + + return r; } static int dss_remove(struct platform_device *pdev) @@ -1473,6 +1476,18 @@ static int dss_remove(struct platform_de dss_uninitialize_debugfs(); + pm_runtime_disable(&pdev->dev); + + dss_uninit_ports(pdev); + + if (dss.video1_pll) + dss_video_pll_uninit(dss.video1_pll); + + if (dss.video2_pll) + dss_video_pll_uninit(dss.video2_pll); + + dss_put_clocks(); + return 0; }