From patchwork Tue Nov 10 14:54:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mario Kleiner X-Patchwork-Id: 7591371 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4F50D9F2F7 for ; Tue, 10 Nov 2015 14:57:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2AF942078A for ; Tue, 10 Nov 2015 14:57:55 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 0365F20639 for ; Tue, 10 Nov 2015 14:57:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9705D6E23A; Tue, 10 Nov 2015 06:57:51 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wm0-f54.google.com (mail-wm0-f54.google.com [74.125.82.54]) by gabe.freedesktop.org (Postfix) with ESMTPS id E39816E23A; Tue, 10 Nov 2015 06:57:49 -0800 (PST) Received: by wmec201 with SMTP id c201so4874233wme.1; Tue, 10 Nov 2015 06:57:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=yB/hqDiwf8YE7KTf2B/b5xkQ0LEfn0jg16gEirQjRKE=; b=rzyQpQo6UFUCSsZedPFlaDB/nqcTsQBXuLPeo7Bf42Zgiunt9b5Z40+VU0AHPFaaXC In057DI+sgiV1PRNwxWTAydh2hNlI2ES72/ud2o8C4om2I/1wtPghfeMdfror+jNXxlt gsoaHtkmek/EAlKadXSN0Ea3O1jM11Rz+4PeZLjydNgwmUHLF0CsDMaLmEMnaqcjTExL BdKSJW93N/Qhb3xXRFKJRBf+puuafS56LS3CDjhe5EWJL7DWn21WpveoscAGB9U5XD0m 8OGSfUsz6KAdZrWPzFCFuTBk3S3eUjExVlBhHZVmIOU1bjHsgiPAWCCblwzOxdx95/f6 SZOA== X-Received: by 10.194.187.41 with SMTP id fp9mr5230078wjc.14.1447167468184; Tue, 10 Nov 2015 06:57:48 -0800 (PST) Received: from twisty.fritz.box (x5f718254.dyn.telefonica.de. [95.113.130.84]) by smtp.gmail.com with ESMTPSA id 20sm20228947wmh.8.2015.11.10.06.57.46 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 10 Nov 2015 06:57:47 -0800 (PST) From: Mario Kleiner To: dri-devel@lists.freedesktop.org Subject: [PATCH] drm/nouveau: Fix pre-nv50 pageflip events (v3) Date: Tue, 10 Nov 2015 15:54:52 +0100 Message-Id: <1447167452-998-1-git-send-email-mario.kleiner.de@gmail.com> X-Mailer: git-send-email 1.9.1 Cc: Daniel Vetter , Ben Skeggs , nouveau@lists.freedesktop.org, daniel.vetter@intel.com, Thierry Reding 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=-4.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 From: Daniel Vetter Apparently pre-nv50 pageflip events happen before the actual vblank period. Therefore that functionality got semi-disabled in commit af4870e406126b7ac0ae7c7ce5751f25ebe60f28 Author: Mario Kleiner Date: Tue May 13 00:42:08 2014 +0200 drm/nouveau/kms/nv04-nv40: fix pageflip events via special case. Unfortunately that hack got uprooted in commit cc1ef118fc099295ae6aabbacc8af94d8d8885eb Author: Thierry Reding Date: Wed Aug 12 17:00:31 2015 +0200 drm/irq: Make pipe unsigned and name consistent Trigering a warning when trying to sample the vblank timestamp for a non-existing pipe. There's a few ways to fix this: - Open-code the old behaviour, which just enshrines this slight breakage of the userspace ABI. - Revert Mario's commit and again inflict broken timestamps, again not pretty. - Fix this for real by delaying the pageflip TS until the next vblank interrupt, thereby making it accurate. This patch implements the third option. Since having a page flip interrupt that happens when the pageflip gets armed and not when it completes in the next vblank seems to be fairly common (older i915 hw works very similarly) create a new helper to arm vblank events for such drivers. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=106431 Cc: Thierry Reding Cc: Mario Kleiner Cc: Ben Skeggs Cc: Ilia Mirkin v2 (mario): Integrate my own review comments into Daniels patch. - Fix function prototypes in drmP.h - Add missing vblank_put() for pageflip completion without pageflip event. - Initialize sequence number for queued pageflip event to avoid trouble in drm_handle_vblank_events(). - Remove dead code and spelling fix. v3 (mario): Add a signed-off-by and cc stable tag per Ilja's advice. Signed-off-by: Daniel Vetter (v1) Reviewed-by: Mario Kleiner (v2/v3) Signed-off-by: Mario Kleiner Cc: stable@vger.kernel.org # v4.3 Tested-by: poma --- drivers/gpu/drm/drm_irq.c | 54 ++++++++++++++++++++++++++++++- drivers/gpu/drm/nouveau/nouveau_display.c | 19 ++++++----- include/drm/drmP.h | 4 +++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index eba6337..819b8c1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -972,7 +972,8 @@ static void send_vblank_event(struct drm_device *dev, struct drm_pending_vblank_event *e, unsigned long seq, struct timeval *now) { - WARN_ON_SMP(!spin_is_locked(&dev->event_lock)); + assert_spin_locked(&dev->event_lock); + e->event.sequence = seq; e->event.tv_sec = now->tv_sec; e->event.tv_usec = now->tv_usec; @@ -985,6 +986,57 @@ static void send_vblank_event(struct drm_device *dev, } /** + * drm_arm_vblank_event - arm vblank event after pageflip + * @dev: DRM device + * @pipe: CRTC index + * @e: the event to prepare to send + * + * A lot of drivers need to generate vblank events for the very next vblank + * interrupt. For example when the page flip interrupt happens when the page + * flip gets armed, but not when it actually executes within the next vblank + * period. This helper function implements exactly the required vblank arming + * behaviour. + * + * Caller must hold event lock. Caller must also hold a vblank reference for the + * event @e, which will be dropped when the next vblank arrives. + * + * This is the legacy version of drm_crtc_arm_vblank_event(). + */ +void drm_arm_vblank_event(struct drm_device *dev, unsigned int pipe, + struct drm_pending_vblank_event *e) +{ + assert_spin_locked(&dev->event_lock); + + e->pipe = pipe; + e->event.sequence = drm_vblank_count(dev, pipe); + list_add_tail(&e->base.link, &dev->vblank_event_list); +} +EXPORT_SYMBOL(drm_arm_vblank_event); + +/** + * drm_arm_vblank_event - arm vblank event after pageflip + * @crtc: the source CRTC of the vblank event + * @e: the event to send + * + * A lot of drivers need to generate vblank events for the very next vblank + * interrupt. For example when the page flip interrupt happens when the page + * flip gets armed, but not when it actually executes within the next vblank + * period. This helper function implements exactly the required vblank arming + * behaviour. + * + * Caller must hold event lock. Caller must also hold a vblank reference for the + * event @e, which will be dropped when the next vblank arrives. + * + * This is the native KMS version of drm_send_vblank_event(). + */ +void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, + struct drm_pending_vblank_event *e) +{ + drm_arm_vblank_event(crtc->dev, drm_crtc_index(crtc), e); +} +EXPORT_SYMBOL(drm_crtc_arm_vblank_event); + +/** * drm_send_vblank_event - helper to send vblank event after pageflip * @dev: DRM device * @pipe: CRTC index diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index db6bc67..64c8d93 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -829,7 +829,6 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, struct drm_device *dev = drm->dev; struct nouveau_page_flip_state *s; unsigned long flags; - int crtcid = -1; spin_lock_irqsave(&dev->event_lock, flags); @@ -841,15 +840,19 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); if (s->event) { - /* Vblank timestamps/counts are only correct on >= NV-50 */ - if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) - crtcid = s->crtc; + if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) { + drm_arm_vblank_event(dev, s->crtc, s->event); + } else { + drm_send_vblank_event(dev, s->crtc, s->event); - drm_send_vblank_event(dev, crtcid, s->event); + /* Give up ownership of vblank for page-flipped crtc */ + drm_vblank_put(dev, s->crtc); + } + } + else { + /* Give up ownership of vblank for page-flipped crtc */ + drm_vblank_put(dev, s->crtc); } - - /* Give up ownership of vblank for page-flipped crtc */ - drm_vblank_put(dev, s->crtc); list_del(&s->head); if (ps) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 4d3b842..02a1512 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -948,6 +948,10 @@ extern void drm_send_vblank_event(struct drm_device *dev, unsigned int pipe, struct drm_pending_vblank_event *e); extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e); +extern void drm_arm_vblank_event(struct drm_device *dev, unsigned int pipe, + struct drm_pending_vblank_event *e); +extern void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, + struct drm_pending_vblank_event *e); extern bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc); extern int drm_vblank_get(struct drm_device *dev, unsigned int pipe);