From patchwork Wed Oct 30 04:13:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mario Kleiner X-Patchwork-Id: 3112931 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id ACF34BF924 for ; Wed, 30 Oct 2013 04:13:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BD3F4201F9 for ; Wed, 30 Oct 2013 04:13:51 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id AF06C201F4 for ; Wed, 30 Oct 2013 04:13:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E4D97EEDD0; Tue, 29 Oct 2013 21:13:46 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from xmailer.gwdg.de (xmailer.gwdg.de [134.76.10.29]) by gabe.freedesktop.org (Postfix) with ESMTP id 1A243EEDCB; Tue, 29 Oct 2013 21:13:38 -0700 (PDT) Received: from smtp-out.tuebingen.mpg.de ([192.124.26.249] helo=tuebingen.mpg.de) by mailer.gwdg.de with esmtp (Exim 4.80) (envelope-from ) id 1VbNA0-0000ei-QX; Wed, 30 Oct 2013 05:13:37 +0100 Received: from fir.kyb.local (account mario.kleiner@tuebingen.mpg.de [10.38.132.250] verified) by tuebingen.mpg.de (CommuniGate Pro SMTP 5.4.2) with ESMTPA id 25913738; Wed, 30 Oct 2013 05:13:36 +0100 From: Mario Kleiner To: airlied@gmail.com Subject: [PATCH 2/4] drm: Push latency sensitive bits of vblank scanoutpos timestamping into kms drivers. Date: Wed, 30 Oct 2013 05:13:06 +0100 Message-Id: <1383106388-32481-3-git-send-email-mario.kleiner.de@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1383106388-32481-1-git-send-email-mario.kleiner.de@gmail.com> References: <1383106388-32481-1-git-send-email-mario.kleiner.de@gmail.com> MIME-Version: 1.0 X-Virus-Scanned: (clean) by exiscan+sophie Cc: intel-gfx@lists.freedesktop.org, mario.kleiner@tuebingen.mpg.de, dri-devel@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@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A change in locking of some kms drivers (currently intel-kms) make the old approach too inaccurate and also incompatible with the PREEMPT_RT realtime kernel patchset. The driver->get_scanout_position() method of intel-kms now needs to aquire a spinlock, which clashes badly with the former preempt_disable() calls in the drm, and it also introduces larger delays and timing uncertainty on a contended lock than acceptable. This patch changes the prototype of driver->get_scanout_position() to require/allow kms drivers to perform the ktime_get() system time queries which go along with actual scanout position readout in a way that provides maximum precision and to return those timestamps to the drm. kms drivers implementations of get_scanout_position() are asked to implement timestamping and scanoutpos readout in a way that is as precise as possible and compatible with preempt_disable() on a PREMPT_RT kernel. A driver should follow this pattern in get_scanout_position() for precision and compatibility: spin_lock...(...); preempt_disable_rt(); // On a PREEMPT_RT kernel, otherwise omit. if (stime) *stime = ktime_get(); ... Minimum amount of MMIO register reads to get scanout position ... ... no taking of locks allowed here! ... if (etime) *etime = ktime_get(); preempt_enable_rt(); // On PREEMPT_RT kernel, otherwise omit. spin_unlock...(...); v2: Fix formatting of new multi-line code comments. Signed-off-by: Mario Kleiner Reviewed-by: Ville Syrjälä Reviewed-by: Alex Deucher --- drivers/gpu/drm/drm_irq.c | 20 ++++++++++++-------- include/drm/drmP.h | 10 ++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 33ee515..d80d952 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -219,7 +219,7 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) for (i = 0; i < num_crtcs; i++) init_waitqueue_head(&dev->vblank[i].queue); - DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); + DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); /* Driver specific high-precision vblank timestamping supported? */ if (dev->driver->get_vblank_timestamp) @@ -586,14 +586,17 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, * code gets preempted or delayed for some reason. */ for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { - /* Get system timestamp before query. */ - stime = ktime_get(); - - /* Get vertical and horizontal scanout pos. vpos, hpos. */ - vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); + /* + * Get vertical and horizontal scanout position vpos, hpos, + * and bounding timestamps stime, etime, pre/post query. + */ + vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, + &hpos, &stime, &etime); - /* Get system timestamp after query. */ - etime = ktime_get(); + /* + * Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if + * CLOCK_REALTIME is requested. + */ if (!drm_timestamp_monotonic) mono_time_offset = ktime_get_monotonic_offset(); @@ -604,6 +607,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, return -EIO; } + /* Compute uncertainty in timestamp of scanout position query. */ duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); /* Accept result with < max_error nsecs timing uncertainty. */ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 2b954ad..48d15f0 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -835,12 +835,17 @@ struct drm_driver { /** * Called by vblank timestamping code. * - * Return the current display scanout position from a crtc. + * Return the current display scanout position from a crtc, and an + * optional accurate ktime_get timestamp of when position was measured. * * \param dev DRM device. * \param crtc Id of the crtc to query. * \param *vpos Target location for current vertical scanout position. * \param *hpos Target location for current horizontal scanout position. + * \param *stime Target location for timestamp taken immediately before + * scanout position query. Can be NULL to skip timestamp. + * \param *etime Target location for timestamp taken immediately after + * scanout position query. Can be NULL to skip timestamp. * * Returns vpos as a positive number while in active scanout area. * Returns vpos as a negative number inside vblank, counting the number @@ -857,7 +862,8 @@ struct drm_driver { * */ int (*get_scanout_position) (struct drm_device *dev, int crtc, - int *vpos, int *hpos); + int *vpos, int *hpos, ktime_t *stime, + ktime_t *etime); /** * Called by \c drm_get_last_vbltimestamp. Should return a precise