From patchwork Fri Jun 10 08:57:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Michel_D=C3=A4nzer?= X-Patchwork-Id: 9169063 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 63EED60573 for ; Fri, 10 Jun 2016 08:57:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50FD42824F for ; Fri, 10 Jun 2016 08:57:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 461202835D; Fri, 10 Jun 2016 08:57:51 +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]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B3F102824F for ; Fri, 10 Jun 2016 08:57:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 87B336ECBC; Fri, 10 Jun 2016 08:57:49 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail.gna.ch (darkcity.gna.ch [195.226.6.51]) by gabe.freedesktop.org (Postfix) with ESMTP id 10E136ECBA for ; Fri, 10 Jun 2016 08:57:21 +0000 (UTC) Received: from kaveri (42-144-27-164.rev.home.ne.jp [42.144.27.164]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by darkcity.gna.ch (Postfix) with ESMTPSA id DA3D6B2AE0D; Fri, 10 Jun 2016 10:59:12 +0200 (CEST) Received: from daenzer by kaveri with local (Exim 4.87) (envelope-from ) id 1bBIFe-0004K4-Le; Fri, 10 Jun 2016 17:57:14 +0900 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 4/5] drm/amdgpu: Wait for end of last waited-for vblank before programming flip Date: Fri, 10 Jun 2016 17:57:12 +0900 Message-Id: <1465549033-16561-5-git-send-email-michel@daenzer.net> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1465549033-16561-1-git-send-email-michel@daenzer.net> References: <1465549033-16561-1-git-send-email-michel@daenzer.net> MIME-Version: 1.0 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 From: Michel Dänzer If userspace wants a page flip to take effect during vblank sequence n, it has to wait for vblank seqno n-1 before calling the DRM_IOCTL_MODE_PAGE_FLIP ioctl. This change makes sure that we do not program the flip to the hardware before the end of vblank seqno n-1 in this case, to prevent the flip from taking effect too early. On the other hand, if the DRM_IOCTL_MODE_PAGE_FLIP ioctl is called during vblank, but userspace didn't wait for the current vblank seqno before, this change would still allow the flip to be programmed during the current vblank seqno. Signed-off-by: Michel Dänzer --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 34 +++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 992f00b..7b53967 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -712,10 +712,11 @@ void amdgpu_doorbell_get_kfd_info(struct amdgpu_device *adev, */ struct amdgpu_flip_work { - struct work_struct flip_work; + struct delayed_work flip_work; struct work_struct unpin_work; struct amdgpu_device *adev; int crtc_id; + u32 avoid_vblank; uint64_t base; struct drm_pending_vblank_event *event; struct amdgpu_bo *old_rbo; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index de95ea7..a9f7851 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -41,7 +41,7 @@ static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb) container_of(cb, struct amdgpu_flip_work, cb); fence_put(f); - schedule_work(&work->flip_work); + schedule_work(&work->flip_work.work); } static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, @@ -63,8 +63,10 @@ static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, static void amdgpu_flip_work_func(struct work_struct *__work) { + struct delayed_work *delayed_work = + container_of(__work, struct delayed_work, work); struct amdgpu_flip_work *work = - container_of(__work, struct amdgpu_flip_work, flip_work); + container_of(delayed_work, struct amdgpu_flip_work, flip_work); struct amdgpu_device *adev = work->adev; struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id]; @@ -81,6 +83,19 @@ static void amdgpu_flip_work_func(struct work_struct *__work) if (amdgpu_flip_handle_fence(work, &work->shared[i])) return; + /* Wait until we're out of the last waited-for vertical blank + * period + */ + if (amdgpuCrtc->enabled && + drm_crtc_vblank_count(crtc) == work->avoid_vblank && + (amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0, + &vpos, &hpos, NULL, NULL, + &crtc->hwmode) + & DRM_SCANOUTPOS_IN_VBLANK)) { + schedule_delayed_work(&work->flip_work, usecs_to_jiffies(1000)); + return; + } + /* We borrow the event spin lock for protecting flip_status */ spin_lock_irqsave(&crtc->dev->event_lock, flags); @@ -175,6 +190,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, uint32_t page_flip_flags) { struct drm_device *dev = crtc->dev; + struct drm_file *file_priv = event->base.file_priv; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct amdgpu_framebuffer *old_amdgpu_fb; @@ -191,7 +207,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, if (work == NULL) return -ENOMEM; - INIT_WORK(&work->flip_work, amdgpu_flip_work_func); + INIT_DELAYED_WORK(&work->flip_work, amdgpu_flip_work_func); INIT_WORK(&work->unpin_work, amdgpu_unpin_work_func); work->event = event; @@ -244,6 +260,16 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, goto pflip_cleanup; } + /* If this file descriptor has waited for the current vblank period, + * do not program the flip during this vblank period + */ + if (amdgpu_crtc->crtc_id < file_priv->num_crtcs) + work->avoid_vblank = + file_priv->last_vblank_wait[amdgpu_crtc->crtc_id]; + + if (!work->avoid_vblank) + work->avoid_vblank = drm_crtc_vblank_count(crtc) - 1; + /* we borrow the event spin lock for protecting flip_wrok */ spin_lock_irqsave(&crtc->dev->event_lock, flags); if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_NONE) { @@ -262,7 +288,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, /* update crtc fb */ crtc->primary->fb = fb; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - amdgpu_flip_work_func(&work->flip_work); + amdgpu_flip_work_func(&work->flip_work.work); return 0; vblank_cleanup: