From patchwork Thu Jun 4 09:02:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 6545901 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 BE1C49F6CE for ; Thu, 4 Jun 2015 11:07:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2D64C2068E for ; Thu, 4 Jun 2015 11:07:15 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id C67FC207BD for ; Thu, 4 Jun 2015 11:07:13 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 533266EB14; Thu, 4 Jun 2015 04:06:41 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from comal.ext.ti.com (comal.ext.ti.com [198.47.26.152]) by gabe.freedesktop.org (Postfix) with ESMTP id 93B976EAD8 for ; Thu, 4 Jun 2015 02:11:55 -0700 (PDT) Received: from dflxv15.itg.ti.com ([128.247.5.124]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id t5494J3Y010382; Thu, 4 Jun 2015 04:04:19 -0500 Received: from DLEE71.ent.ti.com (dlee71.ent.ti.com [157.170.170.114]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id t5494JKY030129; Thu, 4 Jun 2015 04:04:19 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DLEE71.ent.ti.com (157.170.170.114) with Microsoft SMTP Server id 14.3.224.2; Thu, 4 Jun 2015 04:04:18 -0500 Received: from deskari.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id t5493YwY014785; Thu, 4 Jun 2015 04:04:18 -0500 From: Tomi Valkeinen To: , Laurent Pinchart Subject: [PATCHv2 32/45] drm: omapdrm: Support unlinking page flip events prematurely Date: Thu, 4 Jun 2015 12:02:49 +0300 Message-ID: <1433408582-9828-33-git-send-email-tomi.valkeinen@ti.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1433408582-9828-1-git-send-email-tomi.valkeinen@ti.com> References: <1433408582-9828-1-git-send-email-tomi.valkeinen@ti.com> MIME-Version: 1.0 X-Mailman-Approved-At: Thu, 04 Jun 2015 04:06:34 -0700 Cc: Tomi Valkeinen 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-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_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: Laurent Pinchart DRM page flip vblank events requested by page flips or atomic commits are created by the DRM core and then passed to driver through CRTC states (for atomic commit) or directly to the page flip handler (for legacy page flips). The events are then kept aside until the page flip completes, at which point drivers queue them for delivery with a call to drm_send_vblank_event(). When a DRM file handle is closed events pending for delivery are cleaned up automatically by the DRM core. Events that have been passed to the driver but haven't completed yet, however, are not handled by the DRM core. Drivers are responsible for destroying them and must not attempt to queue them for delivery. This is usually handled by drivers' preclose() handlers that cancel and destroy page flip events that reference the file handle being closed. With asynchronous atomic updates the story becomes more complex. Several asynchronous atomic updates can be pending, each of them carrying per-CRTC events. As the atomic_commit() operation doesn't receive a file handle context, drivers can't know which file handle a pending update refers to, making it difficult to cancel or wait for completion of updates related to the file handle being closed. It should be noted that cancelling page flips or waiting for atomic updates completion isn't required by the DRM core when closing a file handle. The only requirement is that no event gets queued for delivery after the preclose() operation returns. This can easily be achieved by storing events for atomic commits in a list, unlinking events from the file handle being closed by setting the file_priv field to NULL, and skipping delivery of unlinked events. This logic replaces the page flip cancellation completely. Signed-off-by: Laurent Pinchart Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 36 +++++++++++------------------------- drivers/gpu/drm/omapdrm/omap_drv.c | 30 +++++++++++++++++++++++++++--- drivers/gpu/drm/omapdrm/omap_drv.h | 2 +- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 8cbac72a1015..aa719ebfe787 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -254,30 +254,6 @@ static const struct dss_mgr_ops mgr_ops = { * Setup, Flush and Page Flip */ -void omap_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) -{ - struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct drm_pending_vblank_event *event; - struct drm_device *dev = crtc->dev; - unsigned long flags; - - /* Destroy the pending vertical blanking event associated with the - * pending page flip, if any, and disable vertical blanking interrupts. - */ - - spin_lock_irqsave(&dev->event_lock, flags); - - event = omap_crtc->event; - omap_crtc->event = NULL; - - if (event && event->base.file_priv == file) { - event->base.destroy(&event->base); - drm_crtc_vblank_put(crtc); - } - - spin_unlock_irqrestore(&dev->event_lock, flags); -} - static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -291,7 +267,17 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) omap_crtc->event = NULL; if (event) { - drm_crtc_send_vblank_event(crtc, event); + list_del(&event->base.link); + + /* + * Queue the event for delivery if it's still linked to a file + * handle, otherwise just destroy it. + */ + if (event->base.file_priv) + drm_crtc_send_vblank_event(crtc, event); + else + event->base.destroy(&event->base); + wake_up(&omap_crtc->flip_wait); drm_crtc_vblank_put(crtc); } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 72a5a88a6419..2e7706355eb6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -118,6 +118,7 @@ static int omap_atomic_commit(struct drm_device *dev, { struct omap_drm_private *priv = dev->dev_private; struct omap_atomic_state_commit *commit; + unsigned long flags; unsigned int i; int ret; @@ -150,6 +151,17 @@ static int omap_atomic_commit(struct drm_device *dev, priv->commit.pending |= commit->crtcs; spin_unlock(&priv->commit.lock); + /* Keep track of all CRTC events to unlink them in preclose(). */ + spin_lock_irqsave(&dev->event_lock, flags); + for (i = 0; i < dev->mode_config.num_crtc; ++i) { + struct drm_crtc_state *cstate = state->crtc_states[i]; + + if (cstate && cstate->event) + list_add_tail(&cstate->event->base.link, + &priv->commit.events); + } + spin_unlock_irqrestore(&dev->event_lock, flags); + /* Swap the state, this is the point of no return. */ drm_atomic_helper_swap_state(dev, state); @@ -632,6 +644,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags) priv->wq = alloc_ordered_workqueue("omapdrm", 0); init_waitqueue_head(&priv->commit.wait); spin_lock_init(&priv->commit.lock); + INIT_LIST_HEAD(&priv->commit.events); spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); @@ -752,12 +765,23 @@ static void dev_lastclose(struct drm_device *dev) static void dev_preclose(struct drm_device *dev, struct drm_file *file) { struct omap_drm_private *priv = dev->dev_private; - unsigned int i; + struct drm_pending_event *event; + unsigned long flags; DBG("preclose: dev=%p", dev); - for (i = 0; i < priv->num_crtcs; ++i) - omap_crtc_cancel_page_flip(priv->crtcs[i], file); + /* + * Unlink all pending CRTC events to make sure they won't be queued up + * by a pending asynchronous commit. + */ + spin_lock_irqsave(&dev->event_lock, flags); + list_for_each_entry(event, &priv->commit.events, link) { + if (event->file_priv == file) { + file->event_space += event->event->length; + event->file_priv = NULL; + } + } + spin_unlock_irqrestore(&dev->event_lock, flags); } static void dev_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index c7ef4d8977ec..81c60284bfb0 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -109,6 +109,7 @@ struct omap_drm_private { /* atomic commit */ struct { + struct list_head events; wait_queue_head_t wait; u32 pending; spinlock_t lock; /* Protects commit.pending */ @@ -142,7 +143,6 @@ void omap_fbdev_free(struct drm_device *dev); const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); -void omap_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); void omap_crtc_pre_init(void); void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev,