All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>
Cc: Alex Deucher <alexdeucher@gmail.com>,
	Daniel Vetter <daniel.vetter@ffwll.ch>,
	Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	Daniel Vetter <daniel.vetter@intel.com>
Subject: [PATCH] drm: Add functions to setup/tear down drm_events.
Date: Sat,  9 Jan 2016 14:27:44 +0100	[thread overview]
Message-ID: <1452346064-19935-1-git-send-email-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <1452285413-28459-3-git-send-email-daniel.vetter@ffwll.ch>

An attempt at not spreading out the file_priv->event_space stuff out
quite so far and wide.  And I think fixes something in ipp_get_event()
that is broken (or if they are doing something more weird/subtle, then
breaks it in a fun way).

Based upon a patch from Rob Clark, rebased and polished.

v2: Spelling fixes (Alex).

Cc: Alex Deucher <alexdeucher@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_atomic.c | 44 ++++++++---------------------
 drivers/gpu/drm/drm_crtc.c   | 36 +++++++-----------------
 drivers/gpu/drm/drm_fops.c   | 67 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drmP.h           |  7 ++++-
 4 files changed, 94 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3f74193885f1..8fb469c4e4b8 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1347,44 +1347,23 @@ static struct drm_pending_vblank_event *create_vblank_event(
 		struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data)
 {
 	struct drm_pending_vblank_event *e = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->event_lock, flags);
-	if (file_priv->event_space < sizeof e->event) {
-		spin_unlock_irqrestore(&dev->event_lock, flags);
-		goto out;
-	}
-	file_priv->event_space -= sizeof e->event;
-	spin_unlock_irqrestore(&dev->event_lock, flags);
+	int ret;
 
 	e = kzalloc(sizeof *e, GFP_KERNEL);
-	if (e == NULL) {
-		spin_lock_irqsave(&dev->event_lock, flags);
-		file_priv->event_space += sizeof e->event;
-		spin_unlock_irqrestore(&dev->event_lock, flags);
-		goto out;
-	}
+	if (!e)
+		return NULL;
 
 	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
-	e->event.base.length = sizeof e->event;
+	e->event.base.length = sizeof(e->event);
 	e->event.user_data = user_data;
-	e->base.event = &e->event.base;
-	e->base.file_priv = file_priv;
-	e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
-
-out:
-	return e;
-}
 
-static void destroy_vblank_event(struct drm_device *dev,
-		struct drm_file *file_priv, struct drm_pending_vblank_event *e)
-{
-	unsigned long flags;
+	ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
+	if (ret) {
+		kfree(e);
+		return NULL;
+	}
 
-	spin_lock_irqsave(&dev->event_lock, flags);
-	file_priv->event_space += sizeof e->event;
-	spin_unlock_irqrestore(&dev->event_lock, flags);
-	kfree(e);
+	return e;
 }
 
 static int atomic_set_prop(struct drm_atomic_state *state,
@@ -1646,8 +1625,7 @@ out:
 			if (!crtc_state->event)
 				continue;
 
-			destroy_vblank_event(dev, file_priv,
-					     crtc_state->event);
+			drm_event_cancel_free(dev, &crtc_state->event->base);
 		}
 	}
 
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 1e75a145834a..60a4184d41b7 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5264,7 +5264,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb = NULL;
 	struct drm_pending_vblank_event *e = NULL;
-	unsigned long flags;
 	int ret = -EINVAL;
 
 	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
@@ -5315,41 +5314,26 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 	}
 
 	if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-		ret = -ENOMEM;
-		spin_lock_irqsave(&dev->event_lock, flags);
-		if (file_priv->event_space < sizeof(e->event)) {
-			spin_unlock_irqrestore(&dev->event_lock, flags);
-			goto out;
-		}
-		file_priv->event_space -= sizeof(e->event);
-		spin_unlock_irqrestore(&dev->event_lock, flags);
-
-		e = kzalloc(sizeof(*e), GFP_KERNEL);
-		if (e == NULL) {
-			spin_lock_irqsave(&dev->event_lock, flags);
-			file_priv->event_space += sizeof(e->event);
-			spin_unlock_irqrestore(&dev->event_lock, flags);
+		e = kzalloc(sizeof *e, GFP_KERNEL);
+		if (!e) {
+			ret = -ENOMEM;
 			goto out;
 		}
-
 		e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
 		e->event.base.length = sizeof(e->event);
 		e->event.user_data = page_flip->user_data;
-		e->base.event = &e->event.base;
-		e->base.file_priv = file_priv;
-		e->base.destroy =
-			(void (*) (struct drm_pending_event *)) kfree;
+		ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
+		if (ret) {
+			kfree(e);
+			goto out;
+		}
 	}
 
 	crtc->primary->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);
-			file_priv->event_space += sizeof(e->event);
-			spin_unlock_irqrestore(&dev->event_lock, flags);
-			kfree(e);
-		}
+		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
+			drm_event_cancel_free(dev, &e->base);
 		/* Keep the old fb, don't unref it. */
 		crtc->primary->old_fb = NULL;
 	} else {
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 73075a1fa380..476408b638e3 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -672,3 +672,70 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
 	return mask;
 }
 EXPORT_SYMBOL(drm_poll);
+
+/**
+ * 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().
+ *
+ * If callers embedded @p into a larger structure it must be allocated with
+ * kmalloc and @p must be the first member element.
+ *
+ * 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 = 0;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+
+	if (file_priv->event_space < e->length) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	file_priv->event_space -= e->length;
+
+	p->event = e;
+	p->file_priv = file_priv;
+
+	/* we *could* pass this in as arg, but everyone uses kfree: */
+	p->destroy = (void (*) (struct drm_pending_event *)) kfree;
+
+out:
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(drm_event_reserve_init);
+
+/**
+ * drm_event_cancel_free - free a DRM event and release it's space
+ * @dev: DRM device
+ * @p: tracking structure for the pending event
+ *
+ * This function frees the event @p initialized with drm_event_reserve_init()
+ * and releases any allocated space.
+ */
+void drm_event_cancel_free(struct drm_device *dev,
+			   struct drm_pending_event *p)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dev->event_lock, flags);
+	p->file_priv->event_space += p->event->length;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+	p->destroy(p);
+}
+EXPORT_SYMBOL(drm_event_cancel_free);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index fc9b9ad5b089..ad4d0a31294d 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -925,8 +925,13 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
 		 size_t count, loff_t *offset);
 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(struct drm_device *dev,
+			   struct drm_file *file_priv,
+			   struct drm_pending_event *p,
+			   struct drm_event *e);
+void drm_event_cancel_free(struct drm_device *dev,
+			   struct drm_pending_event *p);
 
 /* Misc. IOCTL support (drm_ioctl.c) */
 int drm_noop(struct drm_device *dev, void *data,
-- 
2.6.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2016-01-09 13:27 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-08 20:36 [PATCH 00/21] drm_event cleanup Daniel Vetter
2016-01-08 20:36 ` [PATCH 01/21] drm: kerneldoc for drm_fops.c Daniel Vetter
2016-01-08 20:36 ` [PATCH 02/21] drm: Add functions to setup/tear down drm_events Daniel Vetter
2016-01-08 21:10   ` Alex Deucher
2016-01-09 13:27   ` Daniel Vetter [this message]
2016-01-08 20:36 ` [PATCH 03/21] drm/exynos: Use the new event init/free functions Daniel Vetter
2016-01-08 20:36 ` [PATCH 04/21] drm/vmwgfx: " Daniel Vetter
2016-01-08 20:36 ` [PATCH 05/21] drm: Create drm_send_event helpers Daniel Vetter
2016-01-09 13:28   ` [PATCH] " Daniel Vetter
2016-01-08 20:36 ` [PATCH 06/21] drm/fsl: Remove preclose hook Daniel Vetter
2016-01-08 20:36 ` [PATCH 07/21] drm/armada: Remove NULL open/pre/postclose hooks Daniel Vetter
2016-01-08 20:36 ` [PATCH 08/21] drm/gma500: Remove empty preclose hook Daniel Vetter
2016-01-08 20:36 ` [PATCH 09/21] drm: Clean up pending events in the core Daniel Vetter
2016-01-09 13:28   ` [PATCH] " Daniel Vetter
2016-01-10 23:48     ` Laurent Pinchart
2016-01-11 14:51       ` [Intel-gfx] " Daniel Stone
2016-01-14 18:49         ` Laurent Pinchart
2016-01-08 20:36 ` [PATCH 10/21] drm/i915: Nuke intel_modeset_preclose Daniel Vetter
2016-01-08 20:36 ` [PATCH 11/21] drm/atmel: Nuke preclose Daniel Vetter
2016-01-08 20:36 ` [PATCH 12/21] drm/exynos: Remove event cancelling from postclose Daniel Vetter
2016-01-08 20:36 ` [PATCH 13/21] drm/imx: Unconfuse preclose logic Daniel Vetter
2016-01-08 20:36 ` [PATCH 14/21] drm/msm: Nuke preclose hooks Daniel Vetter
2016-01-08 20:36 ` [PATCH 15/21] drm/omap: Nuke close hooks Daniel Vetter
2016-01-11  0:03   ` Laurent Pinchart
2016-01-11  7:10     ` Daniel Vetter
2016-01-08 20:36 ` [PATCH 16/21] drm/rcar: Nuke preclose hook Daniel Vetter
2016-01-11  0:01   ` Laurent Pinchart
2016-01-08 20:36 ` [PATCH 17/21] drm/shmob: " Daniel Vetter
2016-01-10 22:26   ` [PATCH 1/5] " Daniel Vetter
2016-01-10 22:26     ` [PATCH 2/5] drm/tegra: Stop cancelling page flip events Daniel Vetter
2016-01-10 22:26     ` [PATCH 3/5] drm/tilcdc: Nuke preclose hook Daniel Vetter
2016-01-10 22:26     ` [PATCH 4/5] drm/vc4: " Daniel Vetter
2016-01-10 22:26     ` [PATCH 5/5] drm/vmwgfx: " Daniel Vetter
2016-01-11 10:20       ` Thomas Hellstrom
2016-01-11  0:00     ` [PATCH 1/5] drm/shmob: " Laurent Pinchart
2016-01-08 20:36 ` [PATCH 18/21] drm/tegra: Stop cancelling page flip events Daniel Vetter
2016-01-08 20:36 ` [PATCH 19/21] drm/tilcdc: Nuke preclose hook Daniel Vetter
2016-01-08 20:36 ` [PATCH 20/21] drm/vc4: " Daniel Vetter
2016-01-08 20:36 ` [PATCH 21/21] drm/vmwgfx: " Daniel Vetter
2016-01-08 20:53   ` Thomas Hellstrom
2016-01-09 10:43     ` Daniel Vetter
2016-01-10 20:52       ` Thomas Hellstrom
2016-01-10 21:59         ` Daniel Vetter
2016-01-10 22:02   ` [PATCH] " Daniel Vetter
2016-01-10 22:17     ` Thomas Hellstrom
2016-01-10 22:22       ` Daniel Vetter
2016-01-08 21:47 ` [PATCH 00/21] drm_event cleanup Alex Deucher
2016-01-09 13:32 ` Daniel Vetter
2016-01-11 11:20 ` ✗ failure: Fi.CI.BAT Patchwork
2016-01-12 16:24   ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1452346064-19935-1-git-send-email-daniel.vetter@ffwll.ch \
    --to=daniel.vetter@ffwll.ch \
    --cc=alexdeucher@gmail.com \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.