From patchwork Tue Oct 16 22:48:40 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 12281 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id D55F923E57 for ; Tue, 16 Oct 2012 22:48:55 +0000 (UTC) Received: from mail-ia0-f180.google.com (mail-ia0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 4A0CEA1853D for ; Tue, 16 Oct 2012 22:48:55 +0000 (UTC) Received: by mail-ia0-f180.google.com with SMTP id f6so4864267iag.11 for ; Tue, 16 Oct 2012 15:48:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf :dkim-signature:sender:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=HfoEbiTXN0i4yFA9R39x0FWQaMWon6oAiJUwDfgoLQI=; b=kx+Yn1QyhS2EzYlxfstlIvCR1dqHdskf7q38Sl45xTTrMsYixdMBL55X6L7RAizkyR BnwVJjV4QPuH5q/pInOm/iMytDFgZjBgpdl1WCMm6xbk/7RDcnyyArsU0R6YPsVGvRj8 HIiIKyMxuslqZhbEWeXvyneHdAvaBjSuPl20GRb8O91qwHkXmhItwDskouz+Mtoogb5Y aO8WeMLfLSb/S+uxPYlUJd2+g2DlNjsivHbSIuDl2YFGJ+02TFHk/W6j6apDLVuJ2r+4 qSbFMPGKR96wk5okQWbrh6BP0zbA6RcsMYbb6eQegSxgjeRC4HCZ9Bol1fzdw7KTWa8G fQPw== Received: by 10.50.152.137 with SMTP id uy9mr13429065igb.62.1350427734635; Tue, 16 Oct 2012 15:48:54 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp802261igt; Tue, 16 Oct 2012 15:48:53 -0700 (PDT) Received: by 10.60.172.233 with SMTP id bf9mr13521820oec.99.1350427733575; Tue, 16 Oct 2012 15:48:53 -0700 (PDT) Received: from mail-oa0-f50.google.com (mail-oa0-f50.google.com [209.85.219.50]) by mx.google.com with ESMTPS id lg5si21442078obb.38.2012.10.16.15.48.53 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 16 Oct 2012 15:48:53 -0700 (PDT) Received-SPF: pass (google.com: domain of robdclark@gmail.com designates 209.85.219.50 as permitted sender) client-ip=209.85.219.50; Authentication-Results: mx.google.com; spf=pass (google.com: domain of robdclark@gmail.com designates 209.85.219.50 as permitted sender) smtp.mail=robdclark@gmail.com; dkim=pass header.i=@gmail.com Received: by mail-oa0-f50.google.com with SMTP id n16so8441276oag.37 for ; Tue, 16 Oct 2012 15:48:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer; bh=HfoEbiTXN0i4yFA9R39x0FWQaMWon6oAiJUwDfgoLQI=; b=flF8CkUYi54aTzWKCG6laC5CA85vUis0ldY7dIfI5iy3qzPX9OXUhs+8Q4K/wxx3X/ F3SvmU7D1il9I5+cUnS4Sjm0M0PeIe9f+HZ7wg9/AW/2yAKyMZ5Ige+5y5jG4h66rkJn xi4vhDMXuUrliYx266TsfJOdZEN6fTYDJRvKsWUW3ifttYgb5Mcyde/A1ve5UysD02ZQ dO9aVl7d9unLhR17lxQ7qSaNFI1WTXi1wxU6+mqznCOWMLyKEwI3SM3zezwiZu+J2M21 3SOkjeM4lJreb71WFs35FtspmEma1cjxCPzy8Y3q+geNFuovO/6FPT7couLRSVQeX5Sd d6MQ== Received: by 10.60.2.161 with SMTP id 1mr13446625oev.48.1350427733016; Tue, 16 Oct 2012 15:48:53 -0700 (PDT) Received: from localhost (dragon.ti.com. [192.94.94.33]) by mx.google.com with ESMTPS id f3sm15929057obz.8.2012.10.16.15.48.51 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 16 Oct 2012 15:48:51 -0700 (PDT) Sender: Rob Clark From: Rob Clark To: dri-devel@lists.freedesktop.org Cc: patches@linaro.org, laurent.pinchart@ideasonboard.com, Rob Clark Subject: [PATCH 01/11] drm: add drm_send_vblank_event() helper (v5) Date: Tue, 16 Oct 2012 17:48:40 -0500 Message-Id: <1350427720-30450-1-git-send-email-rob.clark@linaro.org> X-Mailer: git-send-email 1.7.9.5 X-Gm-Message-State: ALoCoQlNSvXemRp0sht+lKu8nz0lAEdmDDDag/ZiyN5rzeykq5gx3/rU0H0njnpmCBiSqh/g/R/y From: Rob Clark A helper that drivers can use to send vblank event after a pageflip. If the driver doesn't support proper vblank irq based time/seqn then just pass -1 for the pipe # to get do_gettimestamp() behavior (since there are a lot of drivers that don't use drm_vblank_count_and_time()) Also an internal send_vblank_event() helper for the various other code paths within drm_irq that also need to send vblank events. v1: original v2: add back 'vblwait->reply.sequence = seq' which should not have been deleted v3: add WARN_ON() in case lock is not held and comments v4: use WARN_ON_SMP() instead to fix issue with !SMP && !DEBUG_SPINLOCK as pointed out by Marcin Slusarz v5: update docbook Signed-off-by: Rob Clark --- Documentation/DocBook/drm.tmpl | 20 +++-------- drivers/gpu/drm/drm_irq.c | 74 ++++++++++++++++++++++++++++------------ include/drm/drmP.h | 2 ++ 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index b030052..c9cbb3f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -1141,23 +1141,13 @@ int max_width, max_height; the page_flip operation will be called with a non-NULL event argument pointing to a drm_pending_vblank_event instance. Upon page - flip completion the driver must fill the - event::event - sequence, tv_sec - and tv_usec fields with the associated - vertical blanking count and timestamp, add the event to the - drm_file list of events to be signaled, and wake - up any waiting process. This can be performed with + flip completion the driver must call drm_send_vblank_event + to fill in the event and send to wake up any waiting processes. + This can be performed with event.sequence = drm_vblank_count_and_time(..., &now); - event->event.tv_sec = now.tv_sec; - event->event.tv_usec = now.tv_usec; - spin_lock_irqsave(&dev->event_lock, flags); - list_add_tail(&event->base.link, &event->base.file_priv->event_list); - wake_up_interruptible(&event->base.file_priv->event_wait); + ... + drm_send_vblank_event(dev, pipe, event); spin_unlock_irqrestore(&dev->event_lock, flags); ]]> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 076c4a8..9bdcfd5 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -802,6 +802,46 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, } EXPORT_SYMBOL(drm_vblank_count_and_time); +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)); + e->event.sequence = seq; + e->event.tv_sec = now->tv_sec; + e->event.tv_usec = now->tv_usec; + + list_add_tail(&e->base.link, + &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + trace_drm_vblank_event_delivered(e->base.pid, e->pipe, + e->event.sequence); +} + +/** + * drm_send_vblank_event - helper to send vblank event after pageflip + * @dev: DRM device + * @crtc: CRTC in question + * @e: the event to send + * + * Updates sequence # and timestamp on event, and sends it to userspace. + * Caller must hold event lock. + */ +void drm_send_vblank_event(struct drm_device *dev, int crtc, + struct drm_pending_vblank_event *e) +{ + struct timeval now; + unsigned int seq; + if (crtc >= 0) { + seq = drm_vblank_count_and_time(dev, crtc, &now); + } else { + seq = 0; + do_gettimeofday(&now); + } + send_vblank_event(dev, e, seq, &now); +} +EXPORT_SYMBOL(drm_send_vblank_event); + /** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device @@ -936,6 +976,13 @@ void drm_vblank_put(struct drm_device *dev, int crtc) } EXPORT_SYMBOL(drm_vblank_put); +/** + * drm_vblank_off - disable vblank events on a CRTC + * @dev: DRM device + * @crtc: CRTC in question + * + * Caller must hold event lock. + */ void drm_vblank_off(struct drm_device *dev, int crtc) { struct drm_pending_vblank_event *e, *t; @@ -955,15 +1002,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc) DRM_DEBUG("Sending premature vblank event on disable: \ wanted %d, current %d\n", e->event.sequence, seq); - - e->event.sequence = seq; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; + list_del(&e->base.link); drm_vblank_put(dev, e->pipe); - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - trace_drm_vblank_event_delivered(e->base.pid, e->pipe, - e->event.sequence); + send_vblank_event(dev, e, seq, &now); } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); @@ -1107,15 +1148,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, e->event.sequence = vblwait->request.sequence; if ((seq - vblwait->request.sequence) <= (1 << 23)) { - e->event.sequence = seq; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, pipe); - list_add_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); + send_vblank_event(dev, e, seq, &now); vblwait->reply.sequence = seq; - trace_drm_vblank_event_delivered(current->pid, pipe, - vblwait->request.sequence); } else { /* drm_handle_vblank_events will call drm_vblank_put */ list_add_tail(&e->base.link, &dev->vblank_event_list); @@ -1256,14 +1291,9 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) DRM_DEBUG("vblank event on %d, current %d\n", e->event.sequence, seq); - e->event.sequence = seq; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; + list_del(&e->base.link); drm_vblank_put(dev, e->pipe); - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - trace_drm_vblank_event_delivered(e->base.pid, e->pipe, - e->event.sequence); + send_vblank_event(dev, e, seq, &now); } spin_unlock_irqrestore(&dev->event_lock, flags); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 05af0e7..ee8f927 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1437,6 +1437,8 @@ extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); extern u32 drm_vblank_count(struct drm_device *dev, int crtc); extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, struct timeval *vblanktime); +extern void drm_send_vblank_event(struct drm_device *dev, int crtc, + struct drm_pending_vblank_event *e); extern bool drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc);