Received: by 2002:a05:7412:a9a2:b0:e2:908c:2ebd with SMTP id o34csp2794422rdh; Mon, 30 Oct 2023 07:57:19 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEQs5ROw7VFc0NVRpzM22uj8ebg7mBNJBDddnL/nzAWbsoV3Qm/zj0nh7qsI5QZMgTlM7TL X-Received: by 2002:a05:6870:b14d:b0:1e9:88c2:ba80 with SMTP id a13-20020a056870b14d00b001e988c2ba80mr13015536oal.30.1698677839112; Mon, 30 Oct 2023 07:57:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698677839; cv=none; d=google.com; s=arc-20160816; b=ZawLQaxu0nlA/blVv1dJ5zjHvXz3jt+5+VAjh3QIfnu+KCChUAlgBkQLMZowIoWJZG 6gepxoP0zgWexJzI//schJkrCJi/2tkl98VZAZ+EPylBDY2YWKPVDNOc2dGFuwyREo3E t24kecUyakMrixFKl4gqur7ALXQNyBpIHLXixLm0OiZuzRbjgU3gCJ94kQ7SF9Nq2E4t pKSigEBgdMLwUc5Ny/JBl1cTvrIxCRxpxGHIST2rrl5KUgJFeqQzU+KrLQEu4Gab4f5j LihNxKYIRAJvzwxl0eqbEMGpWCT0LC9hyr5szyN8k0faLSKbXOoZcpS9scaD3DbRx+FK j0ag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:content-language:subject:user-agent:mime-version :date:message-id; bh=1UBIAhXWs9OiDIi1fHs1PzRw2tuBDtqo6/ehruVuDiI=; fh=qPgcJZhyY4n/p0paaaG2joG4slQUL+EqjZOBwmShGMs=; b=B8TTei6bu0EyBItlKUcjGH5Ae9fP3ZCaFQ8zyFM1eYJ9YFIblJxiieURlI7q5UXQ+H syGLVvz51VFgH9GqPIRF+u0Jrx6eZD+jRGZy+5j9WTAQg3iHb+s0yNeJLvJdXanEitcd e4WhfNUqDNg0goI/kh2bQmXLCNOkwHIf9X2MOYRWsrdEYu1sKb2U/h/xCOH8is0R29Fc XxkvukvObHvO0gcbmQ83w9YTe9W+tNEnw9N99vj2B1rJQnYxkFmioMfbD+NKgEWTqUrL DJ7V/YgTcSKxkSRQMcT/Y3zq36obU2UstV89ARngwCwJRN4yQ7eHvV8pURjC3Vuo06PV kD7A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from fry.vger.email (fry.vger.email. [23.128.96.38]) by mx.google.com with ESMTPS id v70-20020a638949000000b005859cd26197si4928417pgd.455.2023.10.30.07.57.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Oct 2023 07:57:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) client-ip=23.128.96.38; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.38 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 1B2B080A2397; Mon, 30 Oct 2023 07:57:16 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233565AbjJ3O5D (ORCPT + 99 others); Mon, 30 Oct 2023 10:57:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233583AbjJ3O5A (ORCPT ); Mon, 30 Oct 2023 10:57:00 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 4727EF9 for ; Mon, 30 Oct 2023 07:56:55 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9783FFEC; Mon, 30 Oct 2023 07:57:36 -0700 (PDT) Received: from [10.57.36.72] (unknown [10.57.36.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 92ACD3F64C; Mon, 30 Oct 2023 07:56:52 -0700 (PDT) Message-ID: Date: Mon, 30 Oct 2023 14:57:00 +0000 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 1/4] drm/panfrost: Implement ability to turn on/off GPU clocks in suspend Content-Language: en-GB To: AngeloGioacchino Del Regno , boris.brezillon@collabora.com Cc: robh@kernel.org, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com, daniel@ffwll.ch, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, wenst@chromium.org, kernel@collabora.com References: <20231030132257.85379-1-angelogioacchino.delregno@collabora.com> <20231030132257.85379-2-angelogioacchino.delregno@collabora.com> From: Steven Price In-Reply-To: <20231030132257.85379-2-angelogioacchino.delregno@collabora.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Mon, 30 Oct 2023 07:57:16 -0700 (PDT) On 30/10/2023 13:22, AngeloGioacchino Del Regno wrote: > Currently, the GPU is being internally powered off for runtime suspend > and turned back on for runtime resume through commands sent to it, but > note that the GPU doesn't need to be clocked during the poweroff state, > hence it is possible to save some power on selected platforms. Looks like a good addition - I suspect some implementations are quite leaky so this could have a meaningful power saving in some cases. > Add suspend and resume handlers for full system sleep and then add > a new panfrost_gpu_pm enumeration and a pm_features variable in the > panfrost_compatible structure: BIT(GPU_PM_CLK_DIS) will be used to > enable this power saving technique only on SoCs that are able to > safely use it. > > Note that this was implemented only for the system sleep case and not > for runtime PM because testing on one of my MediaTek platforms showed > issues when turning on and off clocks aggressively (in PM runtime), > with the GPU locking up and unable to soft reset, eventually resulting > in a full system lockup. I think I know why you saw this - see below. > Doing this only for full system sleep never showed issues in 3 days > of testing by suspending and resuming the system continuously. > > Signed-off-by: AngeloGioacchino Del Regno > --- > drivers/gpu/drm/panfrost/panfrost_device.c | 61 ++++++++++++++++++++-- > drivers/gpu/drm/panfrost/panfrost_device.h | 11 ++++ > 2 files changed, 68 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c > index 28f7046e1b1a..2022ed76a620 100644 > --- a/drivers/gpu/drm/panfrost/panfrost_device.c > +++ b/drivers/gpu/drm/panfrost/panfrost_device.c > @@ -403,7 +403,7 @@ void panfrost_device_reset(struct panfrost_device *pfdev) > panfrost_job_enable_interrupts(pfdev); > } > > -static int panfrost_device_resume(struct device *dev) > +static int panfrost_device_runtime_resume(struct device *dev) > { > struct panfrost_device *pfdev = dev_get_drvdata(dev); > > @@ -413,7 +413,7 @@ static int panfrost_device_resume(struct device *dev) > return 0; > } > > -static int panfrost_device_suspend(struct device *dev) > +static int panfrost_device_runtime_suspend(struct device *dev) > { > struct panfrost_device *pfdev = dev_get_drvdata(dev); > So this function calls panfrost_gpu_power_off() which is simply: void panfrost_gpu_power_off(struct panfrost_device *pfdev) { gpu_write(pfdev, TILER_PWROFF_LO, 0); gpu_write(pfdev, SHADER_PWROFF_LO, 0); gpu_write(pfdev, L2_PWROFF_LO, 0); } So we instruct the GPU to turn off, but don't wait for it to complete. > @@ -426,5 +426,58 @@ static int panfrost_device_suspend(struct device *dev) > return 0; > } > > -EXPORT_GPL_RUNTIME_DEV_PM_OPS(panfrost_pm_ops, panfrost_device_suspend, > - panfrost_device_resume, NULL); > +static int panfrost_device_resume(struct device *dev) > +{ > + struct panfrost_device *pfdev = dev_get_drvdata(dev); > + int ret; > + > + if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS)) { > + ret = clk_enable(pfdev->clock); > + if (ret) > + return ret; > + > + if (pfdev->bus_clock) { > + ret = clk_enable(pfdev->bus_clock); > + if (ret) > + goto err_bus_clk; > + } > + } > + > + ret = pm_runtime_force_resume(dev); > + if (ret) > + goto err_resume; > + > + return 0; > + > +err_resume: > + if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS) && pfdev->bus_clock) > + clk_disable(pfdev->bus_clock); > +err_bus_clk: > + if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS)) > + clk_disable(pfdev->clock); > + return ret; > +} > + > +static int panfrost_device_suspend(struct device *dev) > +{ > + struct panfrost_device *pfdev = dev_get_drvdata(dev); > + int ret; > + > + ret = pm_runtime_force_suspend(dev); > + if (ret) > + return ret; So here we've started shutting down the GPU (pm_runtime_force_suspend eventually calls panfrost_gpu_power_off). But nothing here waits for the GPU to actually finish shutting down. If we're unlucky there's dirty data in the caches (or coherency which can snoop into the caches) so the GPU could be actively making bus cycles... > + > + if (pfdev->comp->pm_features & BIT(GPU_PM_CLK_DIS)) { > + clk_disable(pfdev->clock); ... until its clock goes and everything locks up. Something should be waiting for the power down to complete. Either poll the L2_PWRTRANS_LO register to detect that the L2 is no longer transitioning, or wait for the GPU_IRQ_POWER_CHANGED_ALL interrupt to fire. It would be good to test this with the system suspend doing the full power off, it should be safe so it would be a good stress test. Although whether we want the overhead in normal operation is another matter - so I suspect it should just be for testing purposes. I would hope that we don't actually need the GPU_PM_CLK_DIS feature - this should work as long as the GPU is given the time to shutdown. Although note that actually cutting the power (patches 3 & 4) may expose us to implementation errata - there have been issues with designs not resetting correctly. I'm not sure if those made it into real products or if such bugs are confined to test chips. So for the sake of not causing regressions it's probably not a bad thing to have ;) Steve > + > + if (pfdev->bus_clock) > + clk_disable(pfdev->bus_clock); > + } > + > + return 0; > +} > + > +EXPORT_GPL_DEV_PM_OPS(panfrost_pm_ops) = { > + RUNTIME_PM_OPS(panfrost_device_runtime_suspend, panfrost_device_runtime_resume, NULL) > + SYSTEM_SLEEP_PM_OPS(panfrost_device_suspend, panfrost_device_resume) > +}; > diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h > index 1ef38f60d5dc..d7f179eb8ea3 100644 > --- a/drivers/gpu/drm/panfrost/panfrost_device.h > +++ b/drivers/gpu/drm/panfrost/panfrost_device.h > @@ -25,6 +25,14 @@ struct panfrost_perfcnt; > #define NUM_JOB_SLOTS 3 > #define MAX_PM_DOMAINS 5 > > +/** > + * enum panfrost_gpu_pm - Supported kernel power management features > + * @GPU_PM_CLK_DIS: Allow disabling clocks during system suspend > + */ > +enum panfrost_gpu_pm { > + GPU_PM_CLK_DIS, > +}; > + > struct panfrost_features { > u16 id; > u16 revision; > @@ -75,6 +83,9 @@ struct panfrost_compatible { > > /* Vendor implementation quirks callback */ > void (*vendor_quirk)(struct panfrost_device *pfdev); > + > + /* Allowed PM features */ > + u8 pm_features; > }; > > struct panfrost_device {