From patchwork Thu Jul 23 10:59:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lukas Wunner X-Patchwork-Id: 7000831 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.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6AF22C05AC for ; Wed, 12 Aug 2015 11:40:55 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 69216205D3 for ; Wed, 12 Aug 2015 11:40:54 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 7A954206A5 for ; Wed, 12 Aug 2015 11:40:53 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CE0BB6EB3B; Wed, 12 Aug 2015 04:40:49 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org X-Greylist: delayed 476 seconds by postgrey-1.34 at gabe; Wed, 12 Aug 2015 04:40:46 PDT Received: from mailout1.hostsharing.net (mailout1.hostsharing.net [83.223.95.204]) by gabe.freedesktop.org (Postfix) with ESMTPS id A38BC6EB2B; Wed, 12 Aug 2015 04:40:46 -0700 (PDT) Received: from h08.hostsharing.net (h08.hostsharing.net [83.223.95.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mailout1.hostsharing.net (Postfix) with ESMTPS id D158510192003; Wed, 12 Aug 2015 13:32:48 +0200 (CEST) Received: from localhost (6-38-90-81.adsl.cmo.de [81.90.38.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by h08.hostsharing.net (Postfix) with ESMTPSA id C286960423EA; Wed, 12 Aug 2015 13:32:46 +0200 (CEST) X-Mailbox-Line: From 3313fb587249b00537dbcde127223151652427ec Mon Sep 17 00:00:00 2001 Message-Id: <3313fb587249b00537dbcde127223151652427ec.1439288957.git.lukas@wunner.de> In-Reply-To: References: <29bed586baf62f6be77b7ab0ba1b8f5cb3be3aad.1439288957.git.lukas@wunner.de> <164b43588e80baaddb7a4d1081785c4d03a89c4b.1439288957.git.lukas@wunner.de> <27944adb13aa1ab246ee4a1ebb833e397324d073.1439288957.git.lukas@wunner.de> <2ac3eca0759cedd1009221cbef908605f8d29e1e.1439288957.git.lukas@wunner.de> <832f1cfceab9d9403b541b51733b87110fd8e019.1439288957.git.lukas@wunner.de> <88b49891e95ced43bfb57cc8472bb69985827153.1439288957.git.lukas@wunner.de> <2032c8103fc62d709f10be04a54b4df5c6302ad2.1439288957.git.lukas@wunner.de> <5aa64781469028545deb0f0360f56dad5dbe0057.1439288957.git.lukas@wunner.de> <53015af5b9a91332d3d74ef54fff587395447ecf.1439288957.git.lukas@wunner.de> From: Lukas Wunner Date: Thu, 23 Jul 2015 12:59:31 +0200 Subject: [PATCH v2 17/22] drm/nouveau/timer: Fall back to kernel timer if GPU timer read failed To: dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org Cc: Andreas Heider , Paul Hordiienko , William Brown , Bruno Bierbaumer , Matthew Garrett , Dave Airlie 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: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00, DATE_IN_PAST_96_XX, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham 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 Unloading the nouveau module while the GPU is asleep (e.g. on dual GPU laptops) leads to an infinite loop in nvkm_timer_wait_eq() because the timer read out is 0xffffffffffffffff so the condition of the while loop becomes -1 - (-1) < nsec and stays like that unless the GPU is woken up. Use the kernel timer as fallback in this unlikely event. Synchronize the kernel timer and GPU timer in nv04_timer_init() / gk20a_timer_init() which should get called once on driver initialization and on every resume. Even with this fix applied, unloading the module takes a whopping 167 seconds. This could be reduced by changing the NV_WAIT_DEFAULT timeout from the current (maybe excessive?) 2 seconds to 200 ms. A WARN_ON is spewed out at nouveau_bo.c:398 after 81 seconds and a null pointer dereference occurs in nouveau_cli_destroy(), so there's more to fix here. This patch might also be needed to properly handle a GPU connected via Thunderbolt which is suddenly unplugged. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Paul Hordiienko [MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina] Tested-by: William Brown [MBP 8,2 2011 intel SNB + amd turks pre-retina] Tested-by: Lukas Wunner [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina] Tested-by: Bruno Bierbaumer [MBP 11,3 2013 intel HSW + nvidia GK107 retina -- work in progress] Signed-off-by: Lukas Wunner --- drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c | 4 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c | 9 +++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h | 1 + 3 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c index 80e3806..28d27ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/gk20a.c @@ -41,6 +41,10 @@ gk20a_timer_init(struct nvkm_object *object) /* restore the time before suspend */ nv_wr32(priv, NV04_PTIMER_TIME_1, hi); nv_wr32(priv, NV04_PTIMER_TIME_0, lo); + + /* save kernel time as fallback */ + priv->suspend_ktime = ktime_to_ns(ktime_get()) - priv->suspend_time; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c index 6b7facb..228749d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c @@ -36,6 +36,11 @@ nv04_timer_read(struct nvkm_timer *ptimer) lo = nv_rd32(priv, NV04_PTIMER_TIME_0); } while (hi != nv_rd32(priv, NV04_PTIMER_TIME_1)); + if (unlikely(hi == -1 && lo == -1)) { + nv_spam(priv, "read failed, falling back to kernel timer\n"); + return ktime_to_ns(ktime_get()) - priv->suspend_ktime; + } + return ((u64)hi << 32 | lo); } @@ -216,6 +221,10 @@ nv04_timer_init(struct nvkm_object *object) nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); nv_wr32(priv, NV04_PTIMER_TIME_1, hi); nv_wr32(priv, NV04_PTIMER_TIME_0, lo); + + /* save kernel time as fallback */ + priv->suspend_ktime = ktime_to_ns(ktime_get()) - priv->suspend_time; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h index 89996a9..1b83a0f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.h @@ -15,6 +15,7 @@ struct nv04_timer_priv { struct list_head alarms; spinlock_t lock; u64 suspend_time; + u64 suspend_ktime; }; int nv04_timer_ctor(struct nvkm_object *, struct nvkm_object *,