From: Paulo Zanoni <paulo.r.zanoni@intel.com>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
intel-gfx@lists.freedesktop.org
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Subject: Re: [PATCH] drm/i915: Rework FBC schedule locking
Date: Wed, 21 Mar 2018 12:37:26 -0700 [thread overview]
Message-ID: <1521661046.3150.9.camel@intel.com> (raw)
In-Reply-To: <20180316150121.18664-1-maarten.lankhorst@linux.intel.com>
Em Sex, 2018-03-16 às 16:01 +0100, Maarten Lankhorst escreveu:
> Instead of taking fbc->lock inside the worker, don't take any lock
> and cancel the work synchronously to prevent races. Since the worker
> waits for a vblank before activating, wake up all vblank waiters
> after
> signalling the cancel through unsetting work->scheduled_vblank. This
> will make sure that we don't wait too long when cancelling the
> activation.
>
Ok, so this patch changes stuff and above is a description of what is
changing, but why is this done and how does this solve the bug
referenced? What is the real problem here? Please improve the commit
message: it not only helps future git log readers, but it also helps
reviewers like me understand where you're trying to get. I'm lost here.
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103167
> ---
> drivers/gpu/drm/i915/i915_debugfs.c | 4 +-
> drivers/gpu/drm/i915/i915_drv.h | 3 +-
> drivers/gpu/drm/i915/intel_fbc.c | 76 ++++++++++++++++-----------
> ----------
> 3 files changed, 36 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 98e169636f86..cbf5504de183 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1643,9 +1643,9 @@ static int i915_fbc_status(struct seq_file *m,
> void *unused)
> else
> seq_printf(m, "FBC disabled: %s\n", fbc-
> >no_fbc_reason);
>
> - if (fbc->work.scheduled)
> + if (work_busy(&fbc->work.work))
> seq_printf(m, "FBC worker scheduled on vblank %llu,
> now %llu\n",
> - fbc->work.scheduled_vblank,
> + (u64)atomic64_read(&fbc-
> >work.scheduled_vblank),
> drm_crtc_vblank_count(&fbc->crtc->base));
>
> if (intel_fbc_is_active(dev_priv)) {
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h
> index 9262cfb8aac2..a7a1b0453320 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -558,8 +558,7 @@ struct intel_fbc {
> } params;
>
> struct intel_fbc_work {
> - bool scheduled;
> - u64 scheduled_vblank;
> + atomic64_t scheduled_vblank;
> struct work_struct work;
> } work;
>
> diff --git a/drivers/gpu/drm/i915/intel_fbc.c
> b/drivers/gpu/drm/i915/intel_fbc.c
> index 707d49c12638..20d45bcb6b6b 100644
> --- a/drivers/gpu/drm/i915/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/intel_fbc.c
> @@ -357,10 +357,6 @@ static bool intel_fbc_hw_is_active(struct
> drm_i915_private *dev_priv)
>
> static void intel_fbc_hw_activate(struct drm_i915_private *dev_priv)
> {
> - struct intel_fbc *fbc = &dev_priv->fbc;
> -
> - fbc->active = true;
> -
> if (INTEL_GEN(dev_priv) >= 7)
> gen7_fbc_activate(dev_priv);
> else if (INTEL_GEN(dev_priv) >= 5)
> @@ -407,16 +403,13 @@ static void intel_fbc_work_fn(struct
> work_struct *__work)
> struct intel_fbc_work *work = &fbc->work;
> struct intel_crtc *crtc = fbc->crtc;
> struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[crtc-
> >pipe];
> + u64 vbl;
>
> if (drm_crtc_vblank_get(&crtc->base)) {
> /* CRTC is now off, leave FBC deactivated */
> - mutex_lock(&fbc->lock);
> - work->scheduled = false;
> - mutex_unlock(&fbc->lock);
> return;
> }
>
> -retry:
> /* Delay the actual enabling to let pageflipping cease and
> the
> * display to settle before starting the compression. Note
> that
> * this delay also serves a second purpose: it allows for a
> @@ -425,34 +418,35 @@ static void intel_fbc_work_fn(struct
> work_struct *__work)
> *
> * WaFbcWaitForVBlankBeforeEnable:ilk,snb
> *
> - * It is also worth mentioning that since work-
> >scheduled_vblank can be
> - * updated multiple times by the other threads, hitting the
> timeout is
> - * not an error condition. We'll just end up hitting the
> "goto retry"
> - * case below.
> + * This may be killed by unsetting scheduled_vblank, in
> which
> + * case we return early without activating.
> */
> wait_event_timeout(vblank->queue,
> - drm_crtc_vblank_count(&crtc->base) != work-
> >scheduled_vblank,
> + !(vbl = atomic64_read(&work->scheduled_vblank)) ||
> vbl != drm_crtc_vblank_count(&crtc->base),
> msecs_to_jiffies(50));
>
> - mutex_lock(&fbc->lock);
> + if (vbl)
> + intel_fbc_hw_activate(dev_priv);
>
We can't call this without fbc->lock locked.
> - /* Were we cancelled? */
> - if (!work->scheduled)
> - goto out;
> + drm_crtc_vblank_put(&crtc->base);
> +}
>
> - /* Were we delayed again while this function was sleeping?
> */
> - if (drm_crtc_vblank_count(&crtc->base) == work-
> >scheduled_vblank) {
> - mutex_unlock(&fbc->lock);
> - goto retry;
> - }
> +static void intel_fbc_cancel_activation(struct drm_i915_private
> *dev_priv)
> +{
> + struct intel_fbc *fbc = &dev_priv->fbc;
> + struct intel_crtc *crtc;
> + struct drm_vblank_crtc *vblank;
>
> - intel_fbc_hw_activate(dev_priv);
> + if (!fbc->active)
> + return;
>
> - work->scheduled = false;
> + crtc = fbc->crtc;
> + vblank = &dev_priv->drm.vblank[crtc->pipe];
>
> -out:
> - mutex_unlock(&fbc->lock);
> - drm_crtc_vblank_put(&crtc->base);
> + /* Kill FBC worker if it's waiting */
> + atomic64_set(&fbc->work.scheduled_vblank, 0);
Isn't 0 an actual valid vblank value in case we get enough vblanks to
wrap our counters?
> + wake_up_all(&vblank->queue);
> + cancel_work_sync(&fbc->work.work);
> }
>
> static void intel_fbc_schedule_activation(struct intel_crtc *crtc)
> @@ -471,12 +465,10 @@ static void
> intel_fbc_schedule_activation(struct intel_crtc *crtc)
> return;
> }
>
> - /* It is useless to call intel_fbc_cancel_work() or
> cancel_work() in
> - * this function since we're not releasing fbc.lock, so it
> won't have an
> - * opportunity to grab it to discover that it was cancelled.
> So we just
> - * update the expected jiffy count. */
> - work->scheduled = true;
> - work->scheduled_vblank = drm_crtc_vblank_count(&crtc->base);
> + intel_fbc_cancel_activation(dev_priv);
> + fbc->active = true;
> +
> + atomic64_set(&work->scheduled_vblank,
> drm_crtc_accurate_vblank_count(&crtc->base));
> drm_crtc_vblank_put(&crtc->base);
>
> schedule_work(&work->work);
> @@ -489,13 +481,11 @@ static void intel_fbc_deactivate(struct
> drm_i915_private *dev_priv,
>
> WARN_ON(!mutex_is_locked(&fbc->lock));
>
> - /* Calling cancel_work() here won't help due to the fact
> that the work
> - * function grabs fbc->lock. Just set scheduled to false so
> the work
> - * function can know it was cancelled. */
> - fbc->work.scheduled = false;
> + if (fbc->active) {
> + intel_fbc_cancel_activation(dev_priv);
>
> - if (fbc->active)
> intel_fbc_hw_deactivate(dev_priv);
> + }
>
> fbc->no_fbc_reason = reason;
> }
> @@ -1222,11 +1212,11 @@ void intel_fbc_disable(struct intel_crtc
> *crtc)
> WARN_ON(crtc->active);
>
> mutex_lock(&fbc->lock);
> + intel_fbc_cancel_activation(dev_priv);
> +
> if (fbc->crtc == crtc)
> __intel_fbc_disable(dev_priv);
> mutex_unlock(&fbc->lock);
> -
> - cancel_work_sync(&fbc->work.work);
> }
>
> /**
> @@ -1243,13 +1233,13 @@ void intel_fbc_global_disable(struct
> drm_i915_private *dev_priv)
> return;
>
> mutex_lock(&fbc->lock);
> + intel_fbc_cancel_activation(dev_priv);
> +
> if (fbc->enabled) {
> WARN_ON(fbc->crtc->active);
> __intel_fbc_disable(dev_priv);
> }
> mutex_unlock(&fbc->lock);
> -
> - cancel_work_sync(&fbc->work.work);
> }
>
> static void intel_fbc_underrun_work_fn(struct work_struct *work)
> @@ -1373,11 +1363,11 @@ void intel_fbc_init(struct drm_i915_private
> *dev_priv)
> struct intel_fbc *fbc = &dev_priv->fbc;
>
> INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
> + atomic64_set(&fbc->work.scheduled_vblank, 0);
> INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
> mutex_init(&fbc->lock);
> fbc->enabled = false;
> fbc->active = false;
> - fbc->work.scheduled = false;
>
> if (need_fbc_vtd_wa(dev_priv))
> mkwrite_device_info(dev_priv)->has_fbc = false;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
prev parent reply other threads:[~2018-03-21 19:37 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-16 15:01 [PATCH] drm/i915: Rework FBC schedule locking Maarten Lankhorst
2018-03-16 15:19 ` ✗ Fi.CI.CHECKPATCH: warning for " Patchwork
2018-03-16 15:43 ` Jani Nikula
2018-03-16 15:36 ` ✓ Fi.CI.BAT: success " Patchwork
2018-03-16 18:10 ` ✓ Fi.CI.IGT: " Patchwork
2018-03-21 17:55 ` [PATCH] " Rodrigo Vivi
2018-03-21 19:37 ` Paulo Zanoni [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1521661046.3150.9.camel@intel.com \
--to=paulo.r.zanoni@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=rodrigo.vivi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.