From patchwork Tue Nov 7 06:26:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dhinakaran Pandiyan X-Patchwork-Id: 10045795 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 D95386032D for ; Tue, 7 Nov 2017 07:26:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CB81D29E69 for ; Tue, 7 Nov 2017 07:26:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C045B29FEC; Tue, 7 Nov 2017 07:26:52 +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.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED 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 44DEF29E69 for ; Tue, 7 Nov 2017 07:26:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 110E76E037; Tue, 7 Nov 2017 07:26:50 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTPS id 679406E037; Tue, 7 Nov 2017 07:26:47 +0000 (UTC) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Nov 2017 23:26:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,357,1505804400"; d="scan'208";a="172435575" Received: from dk-thinkpad-x260.jf.intel.com (HELO localhost.localdomain) ([10.54.75.38]) by fmsmga005.fm.intel.com with ESMTP; 06 Nov 2017 23:26:44 -0800 From: Dhinakaran Pandiyan To: intel-gfx@lists.freedesktop.org Subject: [RFC PATCH] drm/vblanks: Deal with HW vblank counter resets. Date: Mon, 6 Nov 2017 22:26:17 -0800 Message-Id: <20171107062617.4227-1-dhinakaran.pandiyan@intel.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 Cc: Daniel Vetter , Rodrigo Vivi , dri-devel@lists.freedesktop.org, Dhinakaran Pandiyan 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Some HW vblank counters reset due to power management events, which messes up the vblank counting logic. This leads to screen freezes with user space waiting on vblank events that may not occur if the counter keeps resetting. For e.g., After the HW vblank counter resets [ 9.007359] [drm:drm_update_vblank_count [drm]] updating vblank count on crtc 0: current=297, diff=4294965389, hw=5 hw_last=1912 So, fall back to the SW counter, computed using vblank timestamps and frame duration, when the HW counter value deviates by 50% of the SW computed value. I have tested this patch on my SKL laptop with i915.enable_psr=1 and it *seems* to solve the screen freeze issue seen with PSR when DMC is loaded. Known issues: 1) The 50% deviation margin is arbitrary. 2) "Redundant vblirq ignored" messages are more frequent. I am sending this as an RFC to get feedback on whether the fall back approach is sane and if it should be implemented in the core. Cc: Daniel Vetter Cc: Rodrigo Vivi Cc: Ville Syrjälä Signed-off-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_vblank.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 57cc6e37c810..8000aae5f1f7 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -190,11 +190,12 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, bool in_vblank_irq) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - u32 cur_vblank, diff; + u32 cur_vblank; bool rc; ktime_t t_vblank; int count = DRM_TIMESTAMP_MAXRETRIES; int framedur_ns = vblank->framedur_ns; + u32 diff = in_vblank_irq ? 1 : 0; /* * Interrupts were disabled prior to this call, so deal with counter @@ -213,26 +214,31 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq); } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); - if (dev->max_vblank_count != 0) { - /* trust the hw counter when it's around */ + if (dev->max_vblank_count) diff = (cur_vblank - vblank->last) & dev->max_vblank_count; - } else if (rc && framedur_ns) { + + if (rc && framedur_ns) { u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + u32 sw_diff; /* * Figure out how many vblanks we've missed based * on the difference in the timestamps and the * frame/field duration. */ - diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); - - if (diff == 0 && in_vblank_irq) + sw_diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + if (sw_diff == 0 && in_vblank_irq) DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored." " diff_ns = %lld, framedur_ns = %d)\n", pipe, (long long) diff_ns, framedur_ns); - } else { - /* some kind of default for drivers w/o accurate vbl timestamping */ - diff = in_vblank_irq ? 1 : 0; + + if (!dev->max_vblank_count) + diff = sw_diff; + else if (sw_diff && abs(diff - sw_diff) > DIV_ROUND_CLOSEST(sw_diff, 2)) { + DRM_DEBUG_VBL("hw vblank counter(%u) deviates from sw (%u)\n", + diff, sw_diff); + diff = sw_diff; + } } /*