Message ID | 20230302235356.3148279-13-robdclark@gmail.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp146236wrd; Thu, 2 Mar 2023 16:28:39 -0800 (PST) X-Google-Smtp-Source: AK7set/bQlroeq43V7DkDLgbF7pKeWMXOJ8FLE3pBMo5DWAJTXRXBSsBRjLWhy0T/cNShGzZ1JAJ X-Received: by 2002:a17:907:980e:b0:8b1:2ebf:386c with SMTP id ji14-20020a170907980e00b008b12ebf386cmr15329453ejc.11.1677803319455; Thu, 02 Mar 2023 16:28:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677803319; cv=none; d=google.com; s=arc-20160816; b=AbRrGWq6TlBjp5Au22DTHanXkAV5BYPeyMOBQl3fz96MkmpvwHlqHeRlo0l4YOe3kC Tr3VU98XObuax8Ob8ZHQ5PeCJYZdGODpEg31dEGhHzcv7Ewkz9OB5GqyjlrJwXfgIDcU hVAzSuncTHIFdMIZzncZiEJutC2Uj7LIddhlGqwmaoUOVpUsCHOwcR9m420cg457O2Jd m8woXE1owmR/9Fb1HGLh410FcGWzrAZEBRohsExf6eVeyEaedfszvRAx17yKdPk+X+nJ wzeyJuU20hDjjl9F3tL82sXkGRTuNuu9VY2YkDDOZS5mLaYZH38vCsJaLGB4QCgnBLmx ge0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=uqyHMdEv/I4h+kB4S5EmXwyYyPXw9FA0QD7a4XeiZZ4=; b=UIfGMxePKdAXms/Eep/XcJX7fgpKZ2DyD5FvVEXRYuod1B0IwzHJahCFAr0nQe9Wqf DHaTISBlCDWHExwY6g0P5JqJee+OiApXO7cBa1aWSjUgGwN7wAzhNuvF9SJRmGqoNs2O hpXUl5g/HSHjK4RFNjaBVzegv/FJwGwOA41zoOXx+UJu16S8eBPboluKwAmnro34Ehya CIMdIHVIU75IImCM3ulk4bW7nq/NGrGUyvqJnX5bg+5mAI3sOyBekAk5Q05ejRq0QKBm lc9uhykl870DQiS9b/sDt9Di7+CH3mmh3XusHryRgn5eE5t5V2s5MiY00NSQ3jZDuHuH eSaw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=GvH33u4c; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bw1-20020a170906c1c100b008b743d946f1si597572ejb.706.2023.03.02.16.28.15; Thu, 02 Mar 2023 16:28:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=GvH33u4c; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230195AbjCBXzI (ORCPT <rfc822;davidbtadokoro@gmail.com> + 99 others); Thu, 2 Mar 2023 18:55:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230115AbjCBXy6 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 2 Mar 2023 18:54:58 -0500 Received: from mail-pl1-x62e.google.com (mail-pl1-x62e.google.com [IPv6:2607:f8b0:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5BB7B59E4F; Thu, 2 Mar 2023 15:54:28 -0800 (PST) Received: by mail-pl1-x62e.google.com with SMTP id i10so967024plr.9; Thu, 02 Mar 2023 15:54:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1677801264; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uqyHMdEv/I4h+kB4S5EmXwyYyPXw9FA0QD7a4XeiZZ4=; b=GvH33u4ccYPMMvCngn68gDNnwWhoeCxXosZu0e9JsjIXSAJ9B7HVO0miTzU4GfQasL DiHqkEitHAba/WWn+Bf6KZMG4unaku8MC/NTdxDRsxoIl1Y8FkSlMcbhifpHL06g7tVW 318F9C1go1ZpYISr7hsngHWdyCPh2uIL7KQNT2jYW9WBBCKMHBttZZ5y0KeKKdaS3Xvp CRgsXPZOavh54ryHILIcCoZylDPBK7JUPd7ISHm/7SsUP3GJUjxVNK6hRATZzOso144F +yz0vNwnNSoeZ4TjxKy/PdTHOIpwLLPj/c01SDVfoSFs93e172c85y7ftL7luLIbaPHj MOPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677801264; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uqyHMdEv/I4h+kB4S5EmXwyYyPXw9FA0QD7a4XeiZZ4=; b=tAFNJqbmLzmmpKA0QuXipttog3W4Vm4DYqjCJ/FgOCetgunA1ahFD/gt88ACwKfMdJ GN9ojOYJwAfOOM8dfBXHmDh+ZrH7D6svhbcicjoowAK85foCQ4+aem5/2RBc5bknDMxY 8R2KvQzXeDBaTzla6E9YCalWNaJzX1Z9ZI/zSLqnxtRe2E9oFurSytUtQSUUadg3EWDP 5Bx41PYvm9+Z1PoPgGB4CAln6HB7FpUIY3vZIHoNHgvceL55qxiZqjX1hoLZKW5KFMlp f8JqPsIAtVLMKEppmIO+LdaCvTbicTe7zGizphQNlrKU7w3rYA5OUyBtXxO3aVwBomC0 ykaw== X-Gm-Message-State: AO0yUKVRNTLqwwTWC4ufsz0qbB150/GnzxwJsgtqA3zWneyRElpyUwg0 3gDzsdJVe6Sb3XMtbHF8Aik= X-Received: by 2002:a17:90b:1e42:b0:237:c209:5b14 with SMTP id pi2-20020a17090b1e4200b00237c2095b14mr13054725pjb.22.1677801264030; Thu, 02 Mar 2023 15:54:24 -0800 (PST) Received: from localhost ([2a00:79e1:abd:4a00:61b:48ed:72ab:435b]) by smtp.gmail.com with ESMTPSA id k11-20020a17090a590b00b0023747b0445fsm2161094pji.14.2023.03.02.15.54.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Mar 2023 15:54:23 -0800 (PST) From: Rob Clark <robdclark@gmail.com> To: dri-devel@lists.freedesktop.org Cc: freedreno@lists.freedesktop.org, Daniel Vetter <daniel@ffwll.ch>, =?utf-8?q?Christian_K=C3=B6nig?= <ckoenig.leichtzumerken@gmail.com>, =?utf-8?q?Michel_D=C3=A4nzer?= <michel@daenzer.net>, Tvrtko Ursulin <tvrtko.ursulin@intel.com>, Rodrigo Vivi <rodrigo.vivi@intel.com>, Alex Deucher <alexander.deucher@amd.com>, Pekka Paalanen <ppaalanen@gmail.com>, Simon Ser <contact@emersion.fr>, Luben Tuikov <luben.tuikov@amd.com>, Rob Clark <robdclark@chromium.org>, Rob Clark <robdclark@gmail.com>, Abhinav Kumar <quic_abhinavk@quicinc.com>, Dmitry Baryshkov <dmitry.baryshkov@linaro.org>, Sean Paul <sean@poorly.run>, David Airlie <airlied@gmail.com>, Sumit Semwal <sumit.semwal@linaro.org>, =?utf-8?q?Christian_K=C3=B6nig?= <christian.koenig@amd.com>, linux-arm-msm@vger.kernel.org (open list:DRM DRIVER FOR MSM ADRENO GPU), linux-kernel@vger.kernel.org (open list), linux-media@vger.kernel.org (open list:DMA BUFFER SHARING FRAMEWORK), linaro-mm-sig@lists.linaro.org (moderated list:DMA BUFFER SHARING FRAMEWORK) Subject: [PATCH v9 12/15] drm/msm: Add deadline based boost support Date: Thu, 2 Mar 2023 15:53:34 -0800 Message-Id: <20230302235356.3148279-13-robdclark@gmail.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230302235356.3148279-1-robdclark@gmail.com> References: <20230302235356.3148279-1-robdclark@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1759304293560595189?= X-GMAIL-MSGID: =?utf-8?q?1759304293560595189?= |
Series |
dma-fence: Deadline awareness
|
|
Commit Message
Rob Clark
March 2, 2023, 11:53 p.m. UTC
From: Rob Clark <robdclark@chromium.org> Track the nearest deadline on a fence timeline and set a timer to expire shortly before to trigger boost if the fence has not yet been signaled. v2: rebase Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/msm_fence.c | 74 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_fence.h | 20 +++++++++ 2 files changed, 94 insertions(+)
Comments
On 03/03/2023 01:53, Rob Clark wrote: > From: Rob Clark <robdclark@chromium.org> > > Track the nearest deadline on a fence timeline and set a timer to expire > shortly before to trigger boost if the fence has not yet been signaled. > > v2: rebase > > Signed-off-by: Rob Clark <robdclark@chromium.org> > --- > drivers/gpu/drm/msm/msm_fence.c | 74 +++++++++++++++++++++++++++++++++ > drivers/gpu/drm/msm/msm_fence.h | 20 +++++++++ > 2 files changed, 94 insertions(+) Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> A small question: do we boost to fit into the deadline or to miss the deadline for as little as possible? If the former is the case, we might need to adjust 3ms depending on the workload. > > diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c > index 56641408ea74..51b461f32103 100644 > --- a/drivers/gpu/drm/msm/msm_fence.c > +++ b/drivers/gpu/drm/msm/msm_fence.c > @@ -8,6 +8,35 @@ > > #include "msm_drv.h" > #include "msm_fence.h" > +#include "msm_gpu.h" > + > +static struct msm_gpu *fctx2gpu(struct msm_fence_context *fctx) > +{ > + struct msm_drm_private *priv = fctx->dev->dev_private; > + return priv->gpu; > +} > + > +static enum hrtimer_restart deadline_timer(struct hrtimer *t) > +{ > + struct msm_fence_context *fctx = container_of(t, > + struct msm_fence_context, deadline_timer); > + > + kthread_queue_work(fctx2gpu(fctx)->worker, &fctx->deadline_work); > + > + return HRTIMER_NORESTART; > +} > + > +static void deadline_work(struct kthread_work *work) > +{ > + struct msm_fence_context *fctx = container_of(work, > + struct msm_fence_context, deadline_work); > + > + /* If deadline fence has already passed, nothing to do: */ > + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) > + return; > + > + msm_devfreq_boost(fctx2gpu(fctx), 2); > +} > > > struct msm_fence_context * > @@ -36,6 +65,13 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, > fctx->completed_fence = fctx->last_fence; > *fctx->fenceptr = fctx->last_fence; > > + hrtimer_init(&fctx->deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); > + fctx->deadline_timer.function = deadline_timer; > + > + kthread_init_work(&fctx->deadline_work, deadline_work); > + > + fctx->next_deadline = ktime_get(); > + > return fctx; > } > > @@ -62,6 +98,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) > spin_lock_irqsave(&fctx->spinlock, flags); > if (fence_after(fence, fctx->completed_fence)) > fctx->completed_fence = fence; > + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) > + hrtimer_cancel(&fctx->deadline_timer); > spin_unlock_irqrestore(&fctx->spinlock, flags); > } > > @@ -92,10 +130,46 @@ static bool msm_fence_signaled(struct dma_fence *fence) > return msm_fence_completed(f->fctx, f->base.seqno); > } > > +static void msm_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) > +{ > + struct msm_fence *f = to_msm_fence(fence); > + struct msm_fence_context *fctx = f->fctx; > + unsigned long flags; > + ktime_t now; > + > + spin_lock_irqsave(&fctx->spinlock, flags); > + now = ktime_get(); > + > + if (ktime_after(now, fctx->next_deadline) || > + ktime_before(deadline, fctx->next_deadline)) { > + fctx->next_deadline = deadline; > + fctx->next_deadline_fence = > + max(fctx->next_deadline_fence, (uint32_t)fence->seqno); > + > + /* > + * Set timer to trigger boost 3ms before deadline, or > + * if we are already less than 3ms before the deadline > + * schedule boost work immediately. > + */ > + deadline = ktime_sub(deadline, ms_to_ktime(3)); > + > + if (ktime_after(now, deadline)) { > + kthread_queue_work(fctx2gpu(fctx)->worker, > + &fctx->deadline_work); > + } else { > + hrtimer_start(&fctx->deadline_timer, deadline, > + HRTIMER_MODE_ABS); > + } > + } > + > + spin_unlock_irqrestore(&fctx->spinlock, flags); > +} > + > static const struct dma_fence_ops msm_fence_ops = { > .get_driver_name = msm_fence_get_driver_name, > .get_timeline_name = msm_fence_get_timeline_name, > .signaled = msm_fence_signaled, > + .set_deadline = msm_fence_set_deadline, > }; > > struct dma_fence * > diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h > index 7f1798c54cd1..cdaebfb94f5c 100644 > --- a/drivers/gpu/drm/msm/msm_fence.h > +++ b/drivers/gpu/drm/msm/msm_fence.h > @@ -52,6 +52,26 @@ struct msm_fence_context { > volatile uint32_t *fenceptr; > > spinlock_t spinlock; > + > + /* > + * TODO this doesn't really deal with multiple deadlines, like > + * if userspace got multiple frames ahead.. OTOH atomic updates > + * don't queue, so maybe that is ok > + */ > + > + /** next_deadline: Time of next deadline */ > + ktime_t next_deadline; > + > + /** > + * next_deadline_fence: > + * > + * Fence value for next pending deadline. The deadline timer is > + * canceled when this fence is signaled. > + */ > + uint32_t next_deadline_fence; > + > + struct hrtimer deadline_timer; > + struct kthread_work deadline_work; > }; > > struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
On Fri, Mar 3, 2023 at 2:10 AM Dmitry Baryshkov <dmitry.baryshkov@linaro.org> wrote: > > On 03/03/2023 01:53, Rob Clark wrote: > > From: Rob Clark <robdclark@chromium.org> > > > > Track the nearest deadline on a fence timeline and set a timer to expire > > shortly before to trigger boost if the fence has not yet been signaled. > > > > v2: rebase > > > > Signed-off-by: Rob Clark <robdclark@chromium.org> > > --- > > drivers/gpu/drm/msm/msm_fence.c | 74 +++++++++++++++++++++++++++++++++ > > drivers/gpu/drm/msm/msm_fence.h | 20 +++++++++ > > 2 files changed, 94 insertions(+) > > Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > > A small question: do we boost to fit into the deadline or to miss the > deadline for as little as possible? If the former is the case, we might > need to adjust 3ms depending on the workload. The goal is as much to run with higher clock on the next frame as it is to not miss a deadline. Ie. we don't want devfreq to come to the conclusion that running at <50% clks is best due to the amount of utilization caused by missing ever other vblank. But 3ms is mostly just "seems like a good compromise" value. It might change. BR, -R > > > > diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c > > index 56641408ea74..51b461f32103 100644 > > --- a/drivers/gpu/drm/msm/msm_fence.c > > +++ b/drivers/gpu/drm/msm/msm_fence.c > > @@ -8,6 +8,35 @@ > > > > #include "msm_drv.h" > > #include "msm_fence.h" > > +#include "msm_gpu.h" > > + > > +static struct msm_gpu *fctx2gpu(struct msm_fence_context *fctx) > > +{ > > + struct msm_drm_private *priv = fctx->dev->dev_private; > > + return priv->gpu; > > +} > > + > > +static enum hrtimer_restart deadline_timer(struct hrtimer *t) > > +{ > > + struct msm_fence_context *fctx = container_of(t, > > + struct msm_fence_context, deadline_timer); > > + > > + kthread_queue_work(fctx2gpu(fctx)->worker, &fctx->deadline_work); > > + > > + return HRTIMER_NORESTART; > > +} > > + > > +static void deadline_work(struct kthread_work *work) > > +{ > > + struct msm_fence_context *fctx = container_of(work, > > + struct msm_fence_context, deadline_work); > > + > > + /* If deadline fence has already passed, nothing to do: */ > > + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) > > + return; > > + > > + msm_devfreq_boost(fctx2gpu(fctx), 2); > > +} > > > > > > struct msm_fence_context * > > @@ -36,6 +65,13 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, > > fctx->completed_fence = fctx->last_fence; > > *fctx->fenceptr = fctx->last_fence; > > > > + hrtimer_init(&fctx->deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); > > + fctx->deadline_timer.function = deadline_timer; > > + > > + kthread_init_work(&fctx->deadline_work, deadline_work); > > + > > + fctx->next_deadline = ktime_get(); > > + > > return fctx; > > } > > > > @@ -62,6 +98,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) > > spin_lock_irqsave(&fctx->spinlock, flags); > > if (fence_after(fence, fctx->completed_fence)) > > fctx->completed_fence = fence; > > + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) > > + hrtimer_cancel(&fctx->deadline_timer); > > spin_unlock_irqrestore(&fctx->spinlock, flags); > > } > > > > @@ -92,10 +130,46 @@ static bool msm_fence_signaled(struct dma_fence *fence) > > return msm_fence_completed(f->fctx, f->base.seqno); > > } > > > > +static void msm_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) > > +{ > > + struct msm_fence *f = to_msm_fence(fence); > > + struct msm_fence_context *fctx = f->fctx; > > + unsigned long flags; > > + ktime_t now; > > + > > + spin_lock_irqsave(&fctx->spinlock, flags); > > + now = ktime_get(); > > + > > + if (ktime_after(now, fctx->next_deadline) || > > + ktime_before(deadline, fctx->next_deadline)) { > > + fctx->next_deadline = deadline; > > + fctx->next_deadline_fence = > > + max(fctx->next_deadline_fence, (uint32_t)fence->seqno); > > + > > + /* > > + * Set timer to trigger boost 3ms before deadline, or > > + * if we are already less than 3ms before the deadline > > + * schedule boost work immediately. > > + */ > > + deadline = ktime_sub(deadline, ms_to_ktime(3)); > > + > > + if (ktime_after(now, deadline)) { > > + kthread_queue_work(fctx2gpu(fctx)->worker, > > + &fctx->deadline_work); > > + } else { > > + hrtimer_start(&fctx->deadline_timer, deadline, > > + HRTIMER_MODE_ABS); > > + } > > + } > > + > > + spin_unlock_irqrestore(&fctx->spinlock, flags); > > +} > > + > > static const struct dma_fence_ops msm_fence_ops = { > > .get_driver_name = msm_fence_get_driver_name, > > .get_timeline_name = msm_fence_get_timeline_name, > > .signaled = msm_fence_signaled, > > + .set_deadline = msm_fence_set_deadline, > > }; > > > > struct dma_fence * > > diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h > > index 7f1798c54cd1..cdaebfb94f5c 100644 > > --- a/drivers/gpu/drm/msm/msm_fence.h > > +++ b/drivers/gpu/drm/msm/msm_fence.h > > @@ -52,6 +52,26 @@ struct msm_fence_context { > > volatile uint32_t *fenceptr; > > > > spinlock_t spinlock; > > + > > + /* > > + * TODO this doesn't really deal with multiple deadlines, like > > + * if userspace got multiple frames ahead.. OTOH atomic updates > > + * don't queue, so maybe that is ok > > + */ > > + > > + /** next_deadline: Time of next deadline */ > > + ktime_t next_deadline; > > + > > + /** > > + * next_deadline_fence: > > + * > > + * Fence value for next pending deadline. The deadline timer is > > + * canceled when this fence is signaled. > > + */ > > + uint32_t next_deadline_fence; > > + > > + struct hrtimer deadline_timer; > > + struct kthread_work deadline_work; > > }; > > > > struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, > > -- > With best wishes > Dmitry >
On 03/03/2023 19:03, Rob Clark wrote: > On Fri, Mar 3, 2023 at 2:10 AM Dmitry Baryshkov > <dmitry.baryshkov@linaro.org> wrote: >> >> On 03/03/2023 01:53, Rob Clark wrote: >>> From: Rob Clark <robdclark@chromium.org> >>> >>> Track the nearest deadline on a fence timeline and set a timer to expire >>> shortly before to trigger boost if the fence has not yet been signaled. >>> >>> v2: rebase >>> >>> Signed-off-by: Rob Clark <robdclark@chromium.org> >>> --- >>> drivers/gpu/drm/msm/msm_fence.c | 74 +++++++++++++++++++++++++++++++++ >>> drivers/gpu/drm/msm/msm_fence.h | 20 +++++++++ >>> 2 files changed, 94 insertions(+) >> >> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> >> >> A small question: do we boost to fit into the deadline or to miss the >> deadline for as little as possible? If the former is the case, we might >> need to adjust 3ms depending on the workload. > > The goal is as much to run with higher clock on the next frame as it > is to not miss a deadline. Ie. we don't want devfreq to come to the > conclusion that running at <50% clks is best due to the amount of > utilization caused by missing ever other vblank. Ack, thanks for the explanation. > > But 3ms is mostly just "seems like a good compromise" value. It might change. > > BR, > -R > >>> >>> diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c >>> index 56641408ea74..51b461f32103 100644 >>> --- a/drivers/gpu/drm/msm/msm_fence.c >>> +++ b/drivers/gpu/drm/msm/msm_fence.c >>> @@ -8,6 +8,35 @@ >>> >>> #include "msm_drv.h" >>> #include "msm_fence.h" >>> +#include "msm_gpu.h" >>> + >>> +static struct msm_gpu *fctx2gpu(struct msm_fence_context *fctx) >>> +{ >>> + struct msm_drm_private *priv = fctx->dev->dev_private; >>> + return priv->gpu; >>> +} >>> + >>> +static enum hrtimer_restart deadline_timer(struct hrtimer *t) >>> +{ >>> + struct msm_fence_context *fctx = container_of(t, >>> + struct msm_fence_context, deadline_timer); >>> + >>> + kthread_queue_work(fctx2gpu(fctx)->worker, &fctx->deadline_work); >>> + >>> + return HRTIMER_NORESTART; >>> +} >>> + >>> +static void deadline_work(struct kthread_work *work) >>> +{ >>> + struct msm_fence_context *fctx = container_of(work, >>> + struct msm_fence_context, deadline_work); >>> + >>> + /* If deadline fence has already passed, nothing to do: */ >>> + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) >>> + return; >>> + >>> + msm_devfreq_boost(fctx2gpu(fctx), 2); >>> +} >>> >>> >>> struct msm_fence_context * >>> @@ -36,6 +65,13 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, >>> fctx->completed_fence = fctx->last_fence; >>> *fctx->fenceptr = fctx->last_fence; >>> >>> + hrtimer_init(&fctx->deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); >>> + fctx->deadline_timer.function = deadline_timer; >>> + >>> + kthread_init_work(&fctx->deadline_work, deadline_work); >>> + >>> + fctx->next_deadline = ktime_get(); >>> + >>> return fctx; >>> } >>> >>> @@ -62,6 +98,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) >>> spin_lock_irqsave(&fctx->spinlock, flags); >>> if (fence_after(fence, fctx->completed_fence)) >>> fctx->completed_fence = fence; >>> + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) >>> + hrtimer_cancel(&fctx->deadline_timer); >>> spin_unlock_irqrestore(&fctx->spinlock, flags); >>> } >>> >>> @@ -92,10 +130,46 @@ static bool msm_fence_signaled(struct dma_fence *fence) >>> return msm_fence_completed(f->fctx, f->base.seqno); >>> } >>> >>> +static void msm_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) >>> +{ >>> + struct msm_fence *f = to_msm_fence(fence); >>> + struct msm_fence_context *fctx = f->fctx; >>> + unsigned long flags; >>> + ktime_t now; >>> + >>> + spin_lock_irqsave(&fctx->spinlock, flags); >>> + now = ktime_get(); >>> + >>> + if (ktime_after(now, fctx->next_deadline) || >>> + ktime_before(deadline, fctx->next_deadline)) { >>> + fctx->next_deadline = deadline; >>> + fctx->next_deadline_fence = >>> + max(fctx->next_deadline_fence, (uint32_t)fence->seqno); >>> + >>> + /* >>> + * Set timer to trigger boost 3ms before deadline, or >>> + * if we are already less than 3ms before the deadline >>> + * schedule boost work immediately. >>> + */ >>> + deadline = ktime_sub(deadline, ms_to_ktime(3)); >>> + >>> + if (ktime_after(now, deadline)) { >>> + kthread_queue_work(fctx2gpu(fctx)->worker, >>> + &fctx->deadline_work); >>> + } else { >>> + hrtimer_start(&fctx->deadline_timer, deadline, >>> + HRTIMER_MODE_ABS); >>> + } >>> + } >>> + >>> + spin_unlock_irqrestore(&fctx->spinlock, flags); >>> +} >>> + >>> static const struct dma_fence_ops msm_fence_ops = { >>> .get_driver_name = msm_fence_get_driver_name, >>> .get_timeline_name = msm_fence_get_timeline_name, >>> .signaled = msm_fence_signaled, >>> + .set_deadline = msm_fence_set_deadline, >>> }; >>> >>> struct dma_fence * >>> diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h >>> index 7f1798c54cd1..cdaebfb94f5c 100644 >>> --- a/drivers/gpu/drm/msm/msm_fence.h >>> +++ b/drivers/gpu/drm/msm/msm_fence.h >>> @@ -52,6 +52,26 @@ struct msm_fence_context { >>> volatile uint32_t *fenceptr; >>> >>> spinlock_t spinlock; >>> + >>> + /* >>> + * TODO this doesn't really deal with multiple deadlines, like >>> + * if userspace got multiple frames ahead.. OTOH atomic updates >>> + * don't queue, so maybe that is ok >>> + */ >>> + >>> + /** next_deadline: Time of next deadline */ >>> + ktime_t next_deadline; >>> + >>> + /** >>> + * next_deadline_fence: >>> + * >>> + * Fence value for next pending deadline. The deadline timer is >>> + * canceled when this fence is signaled. >>> + */ >>> + uint32_t next_deadline_fence; >>> + >>> + struct hrtimer deadline_timer; >>> + struct kthread_work deadline_work; >>> }; >>> >>> struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, >> >> -- >> With best wishes >> Dmitry >>
diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index 56641408ea74..51b461f32103 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -8,6 +8,35 @@ #include "msm_drv.h" #include "msm_fence.h" +#include "msm_gpu.h" + +static struct msm_gpu *fctx2gpu(struct msm_fence_context *fctx) +{ + struct msm_drm_private *priv = fctx->dev->dev_private; + return priv->gpu; +} + +static enum hrtimer_restart deadline_timer(struct hrtimer *t) +{ + struct msm_fence_context *fctx = container_of(t, + struct msm_fence_context, deadline_timer); + + kthread_queue_work(fctx2gpu(fctx)->worker, &fctx->deadline_work); + + return HRTIMER_NORESTART; +} + +static void deadline_work(struct kthread_work *work) +{ + struct msm_fence_context *fctx = container_of(work, + struct msm_fence_context, deadline_work); + + /* If deadline fence has already passed, nothing to do: */ + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) + return; + + msm_devfreq_boost(fctx2gpu(fctx), 2); +} struct msm_fence_context * @@ -36,6 +65,13 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, fctx->completed_fence = fctx->last_fence; *fctx->fenceptr = fctx->last_fence; + hrtimer_init(&fctx->deadline_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + fctx->deadline_timer.function = deadline_timer; + + kthread_init_work(&fctx->deadline_work, deadline_work); + + fctx->next_deadline = ktime_get(); + return fctx; } @@ -62,6 +98,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) spin_lock_irqsave(&fctx->spinlock, flags); if (fence_after(fence, fctx->completed_fence)) fctx->completed_fence = fence; + if (msm_fence_completed(fctx, fctx->next_deadline_fence)) + hrtimer_cancel(&fctx->deadline_timer); spin_unlock_irqrestore(&fctx->spinlock, flags); } @@ -92,10 +130,46 @@ static bool msm_fence_signaled(struct dma_fence *fence) return msm_fence_completed(f->fctx, f->base.seqno); } +static void msm_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) +{ + struct msm_fence *f = to_msm_fence(fence); + struct msm_fence_context *fctx = f->fctx; + unsigned long flags; + ktime_t now; + + spin_lock_irqsave(&fctx->spinlock, flags); + now = ktime_get(); + + if (ktime_after(now, fctx->next_deadline) || + ktime_before(deadline, fctx->next_deadline)) { + fctx->next_deadline = deadline; + fctx->next_deadline_fence = + max(fctx->next_deadline_fence, (uint32_t)fence->seqno); + + /* + * Set timer to trigger boost 3ms before deadline, or + * if we are already less than 3ms before the deadline + * schedule boost work immediately. + */ + deadline = ktime_sub(deadline, ms_to_ktime(3)); + + if (ktime_after(now, deadline)) { + kthread_queue_work(fctx2gpu(fctx)->worker, + &fctx->deadline_work); + } else { + hrtimer_start(&fctx->deadline_timer, deadline, + HRTIMER_MODE_ABS); + } + } + + spin_unlock_irqrestore(&fctx->spinlock, flags); +} + static const struct dma_fence_ops msm_fence_ops = { .get_driver_name = msm_fence_get_driver_name, .get_timeline_name = msm_fence_get_timeline_name, .signaled = msm_fence_signaled, + .set_deadline = msm_fence_set_deadline, }; struct dma_fence * diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h index 7f1798c54cd1..cdaebfb94f5c 100644 --- a/drivers/gpu/drm/msm/msm_fence.h +++ b/drivers/gpu/drm/msm/msm_fence.h @@ -52,6 +52,26 @@ struct msm_fence_context { volatile uint32_t *fenceptr; spinlock_t spinlock; + + /* + * TODO this doesn't really deal with multiple deadlines, like + * if userspace got multiple frames ahead.. OTOH atomic updates + * don't queue, so maybe that is ok + */ + + /** next_deadline: Time of next deadline */ + ktime_t next_deadline; + + /** + * next_deadline_fence: + * + * Fence value for next pending deadline. The deadline timer is + * canceled when this fence is signaled. + */ + uint32_t next_deadline_fence; + + struct hrtimer deadline_timer; + struct kthread_work deadline_work; }; struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,