From patchwork Thu Jan 28 11:01:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 8149261 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 175E5BEEE5 for ; Thu, 28 Jan 2016 11:01:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 42C3320364 for ; Thu, 28 Jan 2016 11:01:08 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 8517420154 for ; Thu, 28 Jan 2016 11:01:02 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E33276E835; Thu, 28 Jan 2016 03:01:01 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-wm0-f48.google.com (mail-wm0-f48.google.com [74.125.82.48]) by gabe.freedesktop.org (Postfix) with ESMTPS id 671BD6E831 for ; Thu, 28 Jan 2016 03:01:00 -0800 (PST) Received: by mail-wm0-f48.google.com with SMTP id p63so19104306wmp.1 for ; Thu, 28 Jan 2016 03:01:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ffwll.ch; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZSzyg3SKLOCHLagyQmPGZGmEtMnuwZTs6//sRqcKY60=; b=SD9x9NakrCFP22qSKI+rWEPio5f92/0wGaX2XXLc+sCGlnygfwSxxv7mocYG/iuEtb 1pgVFI5GArqAedjOCsRztvt5mvoOR7TASqTP3u8MZLOXbktNnkbHtYrOdRz+px/kSFBZ F6QsMxNAkCalzUwyz4wQoRs2IaQ7lj4MjAhaI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZSzyg3SKLOCHLagyQmPGZGmEtMnuwZTs6//sRqcKY60=; b=AxkKX3dcsrZvW/6lKEtnOIMhhAV6zjjZ9LEr21blwnovWtKdYd1zSiYXU83JUvowWv rCwH017zRu8KbKcfn1k+RY31OSSlQvEPUsqwQPY3siqANpvBIyqfodr6ENZb9gZTTp8b WHGd5gFmOGrZlVzhLlUQ7kcHT0PLeS36mETZm1+Xwm+eW/thx60jGR00fNjT728QDqLY KCIjWZJbz1I8BWZVkJZ/c0bFTc8R8cJ6Hr9ZA7BLOhLr1a6/2TptKS2pL/EUtIKfqe37 X/NG0MJEvjTB0zbLqYX00ro8RJkepDoWeC7XHkybM0EXnbSabKgjy41qH9huW1weBXel 1r5Q== X-Gm-Message-State: AG10YOSh5y6lKlFlwdat/NHSrj4AcPavCuKbrgbfmJIUv4EZfZVW+Y0CWChwhbh4/gEKDg== X-Received: by 10.194.161.166 with SMTP id xt6mr2577039wjb.98.1453978858924; Thu, 28 Jan 2016 03:00:58 -0800 (PST) Received: from phenom.ffwll.local ([2a02:168:56c9:0:22cf:30ff:fe4c:37d6]) by smtp.gmail.com with ESMTPSA id 17sm2313340wmy.15.2016.01.28.03.00.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 28 Jan 2016 03:00:58 -0800 (PST) From: Daniel Vetter To: Intel Graphics Development , DRI Development Date: Thu, 28 Jan 2016 12:01:04 +0100 Message-Id: <1453978864-1513-1-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 2.7.0.rc3 In-Reply-To: <1453756616-28942-1-git-send-email-daniel.vetter@ffwll.ch> References: <1453756616-28942-1-git-send-email-daniel.vetter@ffwll.ch> Cc: Alex Deucher , Daniel Vetter , Daniel Stone , Daniel Vetter , Laurent Pinchart Subject: [Intel-gfx] [PATCH] drm/vblank: Use drm_event_reserve_init X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 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=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, 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 Well we can't use that directly since that code must hold dev->event_lock already. Extract an _unlocked version. Embarrassingly I've totally forgotten about this patch and any kind of event-based vblank wait totally blew up, killing the kernel. v2: Pick the right base struct, someone didn't noticed that gcc was unhappy. No bug since the addresses at least matched (Daniel Stone) Cc: Alex Deucher Cc: Daniel Stone Cc: Laurent Pinchart Reviewed-by: Daniel Stone Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fops.c | 64 +++++++++++++++++++++++++++++++++++----------- drivers/gpu/drm/drm_irq.c | 11 +++----- include/drm/drmP.h | 4 +++ 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index e13501e3606e..eb6a02f78697 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -678,7 +678,7 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) EXPORT_SYMBOL(drm_poll); /** - * drm_event_reserve_init - init a DRM event and reserve space for it + * drm_event_reserve_init_locked - init a DRM event and reserve space for it * @dev: DRM device * @file_priv: DRM file private data * @p: tracking structure for the pending event @@ -694,24 +694,20 @@ EXPORT_SYMBOL(drm_poll); * If callers embedded @p into a larger structure it must be allocated with * kmalloc and @p must be the first member element. * + * This is the locked version of drm_event_reserve_init() for callers which + * already hold dev->event_lock. + * * RETURNS: * * 0 on success or a negative error code on failure. */ -int drm_event_reserve_init(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_pending_event *p, - struct drm_event *e) +int drm_event_reserve_init_locked(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_pending_event *p, + struct drm_event *e) { - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dev->event_lock, flags); - - if (file_priv->event_space < e->length) { - ret = -ENOMEM; - goto out; - } + if (file_priv->event_space < e->length) + return -ENOMEM; file_priv->event_space -= e->length; @@ -721,8 +717,46 @@ int drm_event_reserve_init(struct drm_device *dev, /* we *could* pass this in as arg, but everyone uses kfree: */ p->destroy = (void (*) (struct drm_pending_event *)) kfree; -out: + return 0; +} +EXPORT_SYMBOL(drm_event_reserve_init_locked); + +/** + * drm_event_reserve_init - init a DRM event and reserve space for it + * @dev: DRM device + * @file_priv: DRM file private data + * @p: tracking structure for the pending event + * @e: actual event data to deliver to userspace + * + * This function prepares the passed in event for eventual delivery. If the event + * doesn't get delivered (because the IOCTL fails later on, before queuing up + * anything) then the even must be cancelled and freed using + * drm_event_cancel_free(). Successfully initialized events should be sent out + * using drm_send_event() or drm_send_event_locked() to signal completion of the + * asynchronous event to userspace. + * + * If callers embedded @p into a larger structure it must be allocated with + * kmalloc and @p must be the first member element. + * + * Callers which already hold dev->event_lock should use + * drm_event_reserve_init() instead. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ +int drm_event_reserve_init(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_pending_event *p, + struct drm_event *e) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&dev->event_lock, flags); + ret = drm_event_reserve_init_locked(dev, file_priv, p, e); spin_unlock_irqrestore(&dev->event_lock, flags); + return ret; } EXPORT_SYMBOL(drm_event_reserve_init); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 4ec8bca643ac..96d03ac38ef7 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1598,9 +1598,6 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, e->event.base.type = DRM_EVENT_VBLANK; e->event.base.length = sizeof(e->event); e->event.user_data = vblwait->request.signal; - e->base.event = &e->event.base; - e->base.file_priv = file_priv; - e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; spin_lock_irqsave(&dev->event_lock, flags); @@ -1616,12 +1613,12 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, goto err_unlock; } - if (file_priv->event_space < sizeof(e->event)) { - ret = -EBUSY; + ret = drm_event_reserve_init_locked(dev, file_priv, &e->base, + &e->event.base); + + if (ret) goto err_unlock; - } - file_priv->event_space -= sizeof(e->event); seq = drm_vblank_count_and_time(dev, pipe, &now); if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 306ef32ec086..1b71852d0a55 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -926,6 +926,10 @@ ssize_t drm_read(struct file *filp, char __user *buffer, int drm_release(struct inode *inode, struct file *filp); int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv); unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); +int drm_event_reserve_init_locked(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_pending_event *p, + struct drm_event *e); int drm_event_reserve_init(struct drm_device *dev, struct drm_file *file_priv, struct drm_pending_event *p,