From patchwork Tue Sep 9 06:28:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Airlie X-Patchwork-Id: 4866371 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C82A99F32F for ; Tue, 9 Sep 2014 06:28:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E21CC20149 for ; Tue, 9 Sep 2014 06:28:37 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 0E030200ED for ; Tue, 9 Sep 2014 06:28:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C8F7A6E3A5; Mon, 8 Sep 2014 23:28:35 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTP id 15F146E3AA; Mon, 8 Sep 2014 23:28:35 -0700 (PDT) Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s896SYKJ030940 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 9 Sep 2014 02:28:34 -0400 Received: from tyrion-bne-redhat-com.bne.redhat.com (dhcp-41-68.bne.redhat.com [10.64.41.68]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s896SIP2023257; Tue, 9 Sep 2014 02:28:33 -0400 From: Dave Airlie To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org Date: Tue, 9 Sep 2014 16:28:15 +1000 Message-Id: <1410244096-9854-11-git-send-email-airlied@gmail.com> In-Reply-To: <1410244096-9854-1-git-send-email-airlied@gmail.com> References: <1410244096-9854-1-git-send-email-airlied@gmail.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 Subject: [Intel-gfx] [PATCH 10/11] drm/tiled: add page_flip support for multi-crtc monitors X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-6.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 From: Dave Airlie This is OMG bad, but in order to get semantics that don't defeat userspace we have to wait for both flips to complete. So rewrite the event handling code to make sure we wait for all crtcs in the tile group to complete flipping. The main problem otherwise is userspace does add_fb ioctl(PAGE_FLIP, crtc, fb) wait_for_event --> page_flip event rm_fb This rm_fb will forcefully nuke the framebuffer from all crtcs that are currently running, however that causes bad things to happen like the crtc gets turned off. So we need to wait before sending the event so userspace doesn't do this. Otherwise gnome-shell turns off half the display after 5-10 frames. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 31 ++++++++++++++++++++++++++++++- drivers/gpu/drm/drm_irq.c | 7 ++++++- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++---- include/drm/drmP.h | 2 ++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e30518b..dd0649a0 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4771,7 +4771,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, struct drm_pending_vblank_event *e = NULL; unsigned long flags; int ret = -EINVAL; - + int crtc_count = 1; if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || page_flip->reserved != 0) return -EINVAL; @@ -4833,14 +4833,43 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.length = sizeof e->event; e->event.user_data = page_flip->user_data; + e->master = crtc; e->base.event = &e->event.base; e->base.file_priv = file_priv; e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; } + if (!list_empty(&crtc->tile_crtc_list)) { + struct drm_crtc *tile; + + list_for_each_entry(tile, &crtc->tile_crtc_list, tile) { + crtc_count++; + } + if (e) + e->crtc_count = crtc_count; + list_for_each_entry(tile, &crtc->tile_crtc_list, tile) { + struct drm_framebuffer *tile_fb = fb; + + drm_framebuffer_reference(fb); + old_fb = tile->primary->fb; + + ret = tile->funcs->page_flip(tile, fb, e, page_flip->flags); + if (ret) { + old_fb = NULL; + } else { + tile_fb = NULL; + } + if (tile_fb) + drm_framebuffer_unreference(tile_fb); + if (old_fb) + drm_framebuffer_unreference(old_fb); + } + } old_fb = crtc->primary->fb; + ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); + if (ret) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { spin_lock_irqsave(&dev->event_lock, flags); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 08ba120..9eee6e9 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -783,10 +783,15 @@ static void send_vblank_event(struct drm_device *dev, * Caller must hold event lock. */ void drm_send_vblank_event(struct drm_device *dev, int crtc, - struct drm_pending_vblank_event *e) + struct drm_pending_vblank_event *e) { struct timeval now; unsigned int seq; + + e->crtc_count--; + if (e->crtc_count > 0) + return; + if (crtc >= 0) { seq = drm_vblank_count_and_time(dev, crtc, &now); } else { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d074d70..11a6ff3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9153,8 +9153,10 @@ static void do_intel_finish_page_flip(struct drm_device *dev, intel_crtc->unpin_work = NULL; - if (work->event) - drm_send_vblank_event(dev, intel_crtc->pipe, work->event); + if (work->event) { + struct intel_crtc *tmp = to_intel_crtc(work->event->master); + drm_send_vblank_event(dev, tmp->pipe, work->event); + } drm_crtc_vblank_put(crtc); @@ -9795,8 +9797,10 @@ free_work: out_hang: intel_crtc_wait_for_pending_flips(crtc); ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb); - if (ret == 0 && event) - drm_send_vblank_event(dev, pipe, event); + if (ret == 0 && event) { + struct intel_crtc *tmp = to_intel_crtc(event->master); + drm_send_vblank_event(dev, tmp->pipe, event); + } } return ret; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1968907..c6005f6 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -982,6 +982,8 @@ struct drm_pending_vblank_event { struct drm_pending_event base; int pipe; struct drm_event_vblank event; + int crtc_count; + struct drm_crtc *master; }; struct drm_vblank_crtc {