From patchwork Tue Nov 21 19:40:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jordan Crouse X-Patchwork-Id: 10068833 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8E45C6038F for ; Tue, 21 Nov 2017 19:41:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 76AE32997A for ; Tue, 21 Nov 2017 19:41:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6B3ED2997D; Tue, 21 Nov 2017 19:41:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D20602997A for ; Tue, 21 Nov 2017 19:41:15 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 302F36E5B4; Tue, 21 Nov 2017 19:41:10 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id B56BF6E5B2; Tue, 21 Nov 2017 19:41:07 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id A02A160860; Tue, 21 Nov 2017 19:41:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1511293267; bh=Xco6k1PRMOZBcfoPu/C3VyxjYuvfaDoeH7AhY+PtvtA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HU5tQuozuZaBJkjXsD+p5pKQaGDcmzVrPL0cm9Ivh8+D5hgdsmKCh4pu5+0Pu+pdT isB4qFfXzsrWaxMt2X60/4KkHFX22X8KEpA85TIzw7eqF7r2sy4dgaxPD772PoIYKH Z/VS1tdkOkzt4hTdFhvTraBJkUi/s2jpJYhnzolg= Received: from jcrouse-lnx.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: jcrouse@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id CCAE36084A; Tue, 21 Nov 2017 19:41:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1511293267; bh=Xco6k1PRMOZBcfoPu/C3VyxjYuvfaDoeH7AhY+PtvtA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HU5tQuozuZaBJkjXsD+p5pKQaGDcmzVrPL0cm9Ivh8+D5hgdsmKCh4pu5+0Pu+pdT isB4qFfXzsrWaxMt2X60/4KkHFX22X8KEpA85TIzw7eqF7r2sy4dgaxPD772PoIYKH Z/VS1tdkOkzt4hTdFhvTraBJkUi/s2jpJYhnzolg= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org CCAE36084A Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=jcrouse@codeaurora.org From: Jordan Crouse To: freedreno@lists.freedesktop.org Subject: [PATCH 8/8] drm/msm/gpu: Add devfreq support for the GPU Date: Tue, 21 Nov 2017 12:40:58 -0700 Message-Id: <1511293258-12415-9-git-send-email-jcrouse@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1511293258-12415-1-git-send-email-jcrouse@codeaurora.org> References: <1511293258-12415-1-git-send-email-jcrouse@codeaurora.org> Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 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-Virus-Scanned: ClamAV using ClamSMTP Add support for devfreq to dynamically control the GPU frequency. By default try to use the 'simple_ondemand' governor which can adjust the frequency based on GPU load. Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 12 +++++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 1 - drivers/gpu/drm/msm/msm_gpu.c | 90 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_gpu.h | 7 +++ 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 56c2c44..7e09d44 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -600,6 +600,9 @@ static int a5xx_hw_init(struct msm_gpu *gpu) /* Select CP0 to always count cycles */ gpu_write(gpu, REG_A5XX_CP_PERFCTR_CP_SEL_0, PERF_CP_ALWAYS_COUNT); + /* Select RBBM0 to countable 6 to get the busy status for devfreq */ + gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); + /* Increase VFD cache access so LRZ and other data gets evicted less */ gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02); @@ -1170,6 +1173,14 @@ static struct msm_ringbuffer *a5xx_active_ring(struct msm_gpu *gpu) return a5xx_gpu->cur_ring; } +static int a5xx_gpu_busy(struct msm_gpu *gpu, uint64_t *value) +{ + *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO, + REG_A5XX_RBBM_PERFCTR_RBBM_0_HI); + + return 0; +} + static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -1185,6 +1196,7 @@ static struct msm_ringbuffer *a5xx_active_ring(struct msm_gpu *gpu) #ifdef CONFIG_DEBUG_FS .show = a5xx_show, #endif + .gpu_busy = a5xx_gpu_busy, }, .get_timestamp = a5xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index b4bac84..de63ff2 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -22,7 +22,6 @@ #include "msm_gem.h" #include "msm_mmu.h" - int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 3d00e7a..243e06e 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -21,12 +21,90 @@ #include "msm_fence.h" #include +#include +#include /* * Power Management: */ +static int msm_devfreq_target(struct device *dev, unsigned long *freq, + u32 flags) +{ + struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); + struct dev_pm_opp *opp; + + opp = dev_pm_opp_find_freq_ceil(dev, freq); + + if (!IS_ERR(opp)) { + clk_set_rate(gpu->core_clk, *freq); + dev_pm_opp_put(opp); + } + + return 0; +} + +static int msm_devfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *status) +{ + struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); + u64 cycles; + ktime_t time; + + status->current_frequency = (unsigned long) clk_get_rate(gpu->core_clk); + gpu->funcs->gpu_busy(gpu, &cycles); + + status->busy_time = (cycles - gpu->devfreq.busy_cycles) / + (status->current_frequency / 1000000); + + gpu->devfreq.busy_cycles = cycles; + + time = ktime_get(); + status->total_time = ktime_us_delta(time, gpu->devfreq.time); + gpu->devfreq.time = time; + + return 0; +} + +static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) +{ + struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); + + *freq = (unsigned long) clk_get_rate(gpu->core_clk); + + return 0; +} + +static struct devfreq_dev_profile msm_devfreq_profile = { + .polling_ms = 10, + .target = msm_devfreq_target, + .get_dev_status = msm_devfreq_get_dev_status, + .get_cur_freq = msm_devfreq_get_cur_freq, +}; + +static void msm_devfreq_init(struct msm_gpu *gpu) +{ + /* We need target support to do devfreq */ + if (!gpu->funcs->gpu_busy) + return; + + msm_devfreq_profile.initial_freq = gpu->fast_rate; + + /* + * Don't set the freq_table or max_state and let devfreq build the table + * from OPP + */ + + gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev, + &msm_devfreq_profile, "simple_ondemand", NULL); + + if (IS_ERR(gpu->devfreq.devfreq)) { + dev_err(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n"); + gpu->devfreq.devfreq = NULL; + } +} + static int enable_pwrrail(struct msm_gpu *gpu) { struct drm_device *dev = gpu->dev; @@ -140,6 +218,13 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu) if (ret) return ret; + if (gpu->devfreq.devfreq) { + gpu->devfreq.busy_cycles = 0; + gpu->devfreq.time = ktime_get(); + + devfreq_resume_device(gpu->devfreq.devfreq); + } + gpu->needs_hw_init = true; return 0; @@ -151,6 +236,9 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu) DBG("%s", gpu->name); + if (gpu->devfreq.devfreq) + devfreq_suspend_device(gpu->devfreq.devfreq); + ret = disable_axi(gpu); if (ret) return ret; @@ -721,6 +809,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->pdev = pdev; platform_set_drvdata(pdev, gpu); + msm_devfreq_init(gpu); + gpu->aspace = msm_gpu_create_address_space(gpu, pdev, config->va_start, config->va_end); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 0de26b6..fccfccd 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -66,6 +66,7 @@ struct msm_gpu_funcs { /* show GPU status in debugfs: */ void (*show)(struct msm_gpu *gpu, struct seq_file *m); #endif + int (*gpu_busy)(struct msm_gpu *gpu, uint64_t *value); }; struct msm_gpu { @@ -120,6 +121,12 @@ struct msm_gpu { struct work_struct recover_work; struct drm_gem_object *memptrs_bo; + + struct { + struct devfreq *devfreq; + u64 busy_cycles; + ktime_t time; + } devfreq; }; /* It turns out that all targets use the same ringbuffer size */