From patchwork Wed Dec 12 16:16:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?VmlsbGUgU3lyasOkbMOk?= X-Patchwork-Id: 1869641 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 48BF3DF266 for ; Wed, 12 Dec 2012 18:15:49 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4B452E655C for ; Wed, 12 Dec 2012 10:15:49 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id BD4B2E6014; Wed, 12 Dec 2012 08:21:33 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 12 Dec 2012 08:21:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.84,267,1355126400"; d="scan'208";a="261178428" Received: from stinkbox.fi.intel.com (HELO stinkbox) ([10.237.72.168]) by fmsmga001.fm.intel.com with SMTP; 12 Dec 2012 08:21:31 -0800 Received: by stinkbox (sSMTP sendmail emulation); Wed, 12 Dec 2012 18:21:30 +0200 From: ville.syrjala@linux.intel.com To: dri-devel@lists.freedesktop.org Subject: [PATCH 78/81] HACK: drm/i915: Make non-blocking GPU synchronization optional Date: Wed, 12 Dec 2012 18:16:45 +0200 Message-Id: <1355329008-31459-79-git-send-email-ville.syrjala@linux.intel.com> X-Mailer: git-send-email 1.7.8.6 In-Reply-To: <1355329008-31459-1-git-send-email-ville.syrjala@linux.intel.com> References: <1355329008-31459-1-git-send-email-ville.syrjala@linux.intel.com> MIME-Version: 1.0 Cc: intel-gfx@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: Ville Syrjälä Add a module parameter that allows one to easily change between blocking and non-blocking GPU synchronization with atomic page flips. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_stub.c | 5 ++ drivers/gpu/drm/i915/i915_trace.h | 49 ++++++++++++++ drivers/gpu/drm/i915/intel_atomic.c | 119 ++++++++++++++++++++++++++++++++++- 3 files changed, 172 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 200e104..b73fde8 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -52,6 +52,9 @@ EXPORT_SYMBOL(drm_timestamp_precision); */ unsigned int drm_timestamp_monotonic = 1; +unsigned int drm_async_gpu = 1; /* 1 to enable async gpu wait */ +EXPORT_SYMBOL(drm_async_gpu); + MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); @@ -59,11 +62,13 @@ MODULE_PARM_DESC(debug, "Enable debug output"); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); +MODULE_PARM_DESC(async_gpu, "Async GPU wait"); module_param_named(debug, drm_debug, int, 0600); module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); +module_param_named(async_gpu, drm_async_gpu, int, 0600); struct idr drm_minors_idr; diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index f71e1b3..754a204 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -16,6 +16,55 @@ /* object tracking */ +TRACE_EVENT(i915_atomic_flip, + TP_PROTO(bool sprite, int pipe, int action, u32 commit_surf, u32 commit_surflive, u32 surf, u32 surflive, u32 iir, u32 commit_dsl, u32 dsl, u32 flip_vbl_count, u32 vbl_count), + TP_ARGS(sprite, pipe, action, commit_surf, commit_surflive, surf, surflive, iir, commit_dsl, dsl, flip_vbl_count, vbl_count), + + TP_STRUCT__entry( + __field(bool, sprite) + __field(int, pipe) + __field(int, action) + __field(u32, commit_surf) + __field(u32, commit_surflive) + __field(u32, surf) + __field(u32, surflive) + __field(u32, iir) + __field(u32, commit_dsl) + __field(u32, dsl) + __field(u32, flip_vbl_count) + __field(u32, vbl_count) + ), + + TP_fast_assign( + __entry->sprite = sprite; + __entry->pipe = pipe; + __entry->action = action; + __entry->commit_surf = commit_surf; + __entry->commit_surflive = commit_surflive; + __entry->surf = surf; + __entry->surflive = surflive; + __entry->iir = iir; + __entry->commit_dsl = commit_dsl; + __entry->dsl = dsl; + __entry->flip_vbl_count = flip_vbl_count; + __entry->vbl_count = vbl_count; + ), + + TP_printk( + "%s/%d %s commit_surf=%x commit_surflive=%x surf=%x surflive=%x iir=%x commit_dsl=%u dsl=%u flip_vbl_count=%u vbl_count=%u", + __entry->sprite ? "SPR" : "DSP", __entry->pipe, + __entry->action == 0 ? "new" : + __entry->action == 1 ? "flipped" : + __entry->action == 2 ? "not flipped" : + __entry->action == 3 ? "missed flipped" : "?", + __entry->commit_surf, __entry->commit_surflive, + __entry->surf, __entry->surflive, + __entry->iir, + __entry->commit_dsl, __entry->dsl, + __entry->flip_vbl_count, __entry->vbl_count + ) +); + TRACE_EVENT(i915_flip_queue_len, TP_PROTO(unsigned int queue_len), TP_ARGS(queue_len), diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index ef5e352..c964b64a 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -47,6 +47,8 @@ #define USE_WRITE_SEQNO +//#define SURFLIVE_DEBUG + struct intel_flip { struct drm_flip base; u32 vbl_count; @@ -64,6 +66,11 @@ struct intel_flip { unsigned int flip_seq; /* FIXME need cursor regs too */ struct intel_plane_regs regs; +#ifdef SURFLIVE_DEBUG + u32 commit_dsl; + u32 commit_surf; + u32 commit_surflive; +#endif }; struct intel_plane_state { @@ -835,11 +842,13 @@ static void unpin_fbs(struct drm_device *dev, } } +extern unsigned int drm_async_gpu; + static int pin_fbs(struct drm_device *dev, struct intel_atomic_state *s) { int i, ret; - bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK; + bool nonblock = drm_async_gpu && (s->flags & DRM_MODE_ATOMIC_NONBLOCK); for (i = 0; i < dev->mode_config.num_crtc; i++) { struct intel_crtc_state *st = &s->crtc[i]; @@ -1971,6 +1980,48 @@ static void intel_flip_prepare(struct drm_flip *flip) } } +#ifdef SURFLIVE_DEBUG +enum flip_action { + _NEW, + _FLIPPED, + _NOT_FLIPPED, + _MISSED_FLIPPED, +}; + +static void trace_flip(struct intel_flip *intel_flip, enum flip_action action) +{ + struct drm_crtc *crtc = intel_flip->crtc; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = to_intel_crtc(crtc)->pipe; + u32 surf; + u32 surflive; + u32 dsl; + u32 iir; + u32 vbl_count; + + if (intel_flip->plane) { + surf = I915_READ(SPRSURF(pipe)); + surflive = I915_READ(SPRSURFLIVE(pipe)); + } else { + surf = I915_READ(DSPSURF(pipe)); + surflive = I915_READ(DSPSURFLIVE(pipe)); + } + dsl = I915_READ(PIPEDSL(pipe)); + iir = I915_READ(DEIIR); + vbl_count = get_vbl_count(crtc); + + trace_i915_atomic_flip(intel_flip->plane != NULL, pipe, action, + intel_flip->commit_surf, intel_flip->commit_surflive, + surf, surflive, iir, intel_flip->commit_dsl, dsl, + intel_flip->vbl_count, vbl_count); +} +#endif + +#ifdef SURFLIVE_DEBUG +static unsigned int missed_flips; +#endif + static bool intel_flip_flip(struct drm_flip *flip, struct drm_flip *pending_flip) { @@ -1980,6 +2031,9 @@ static bool intel_flip_flip(struct drm_flip *flip, struct drm_device *dev = crtc->dev; int pipe = intel_crtc->pipe; u32 vbl_count; +#ifdef SURFLIVE_DEBUG + struct drm_i915_private *dev_priv = dev->dev_private; +#endif intel_flip->vblank_ref = drm_vblank_get(dev, pipe) == 0; @@ -1991,10 +2045,26 @@ static bool intel_flip_flip(struct drm_flip *flip, struct intel_plane *intel_plane = to_intel_plane(plane); intel_plane->commit(plane, &intel_flip->regs); + +#ifdef SURFLIVE_DEBUG + intel_flip->commit_dsl = I915_READ(PIPEDSL(pipe)); + intel_flip->commit_surf = I915_READ(SPRSURF(pipe)); + intel_flip->commit_surflive = I915_READ(SPRSURFLIVE(pipe)); + if (intel_flip->commit_surf != intel_flip->regs.surf) + pr_err("SPRITE SURF MISMATCH\n"); +#endif } else { struct drm_i915_private *dev_priv = dev->dev_private; dev_priv->display.commit_plane(crtc, &intel_flip->regs); + +#ifdef SURFLIVE_DEBUG + intel_flip->commit_dsl = I915_READ(PIPEDSL(pipe)); + intel_flip->commit_surf = I915_READ(DSPSURF(pipe)); + intel_flip->commit_surflive = I915_READ(DSPSURFLIVE(pipe)); + if (intel_flip->commit_surf != intel_flip->regs.surf) + pr_err("PRIMARY PLANE SURF MISMATCH\n"); +#endif } if (intel_flip->has_cursor) @@ -2011,16 +2081,38 @@ static bool intel_flip_flip(struct drm_flip *flip, else intel_flip->vbl_count = (vbl_count + 1) & 0xffffff; +#ifdef SURFLIVE_DEBUG + trace_flip(intel_flip, _NEW); +#endif + if (pending_flip) { struct intel_flip *old_intel_flip = container_of(pending_flip, struct intel_flip, base); bool flipped = intel_vbl_check(pending_flip, vbl_count); if (!flipped) { +#ifdef SURFLIVE_DEBUG + u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe)); + if (old_intel_flip->commit_surflive != surflive) + trace_flip(old_intel_flip, _NOT_FLIPPED); +#endif swap(intel_flip->old_fb_id, old_intel_flip->old_fb_id); swap(intel_flip->old_bo, old_intel_flip->old_bo); swap(intel_flip->old_cursor_bo, old_intel_flip->old_cursor_bo); } +#ifdef SURFLIVE_DEBUG + else { + u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe)); + if (old_intel_flip->commit_surf != surflive) { + trace_flip(old_intel_flip, _FLIPPED); + missed_flips++; + return false; + } + if (missed_flips) + trace_flip(old_intel_flip, _MISSED_FLIPPED); + missed_flips = 0; + } +#endif return flipped; } @@ -2034,7 +2126,26 @@ static bool intel_flip_vblank(struct drm_flip *pending_flip) container_of(pending_flip, struct intel_flip, base); u32 vbl_count = get_vbl_count(old_intel_flip->crtc); +#ifdef SURFLIVE_DEBUG + struct drm_i915_private *dev_priv = old_intel_flip->crtc->dev->dev_private; + int pipe = to_intel_crtc(old_intel_flip->crtc)->pipe; + bool flipped; + flipped = intel_vbl_check(pending_flip, vbl_count); + if (flipped) { + u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe)); + if (old_intel_flip->commit_surf != surflive) { + trace_flip(old_intel_flip, _FLIPPED); + missed_flips++; + return false; + } + if (missed_flips) + trace_flip(old_intel_flip, _MISSED_FLIPPED); + missed_flips = 0; + } + return flipped; +#else return intel_vbl_check(pending_flip, vbl_count); +#endif } static const struct drm_flip_helper_funcs intel_flip_funcs = { @@ -2396,6 +2507,12 @@ static void atomic_pipe_commit(struct drm_device *dev, if (list_empty(&flips)) return; + if (!drm_async_gpu) { + struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe)); + intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips); + return; + } + mutex_lock(&dev->struct_mutex); list_for_each_entry(intel_flip, &flips, base.list) {