All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers)
@ 2013-08-07 17:41 Rob Clark
  2013-08-07 17:41 ` [PATCH 1/9] drm: add flip-work helper Rob Clark
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

I'd sent these previously, but consolidating them into one patchset
for easier tracking.  The individual driver patches are not needed
for msm drm/kms but the drm core bits are.

Rob Clark (9):
  drm: add flip-work helper
  drm/tilcdc: use flip-work helper
  drm/omap: use flip-work helper
  drm: const'ify ioctls table (v2)
  drm/gem: add drm_gem_create_mmap_offset_size()
  drm/gem: add shmem get/put page helpers
  drm/gma500: use gem get/put page helpers
  drm/udl: use gem get/put page helpers
  drm/omap: kill omap_gem_helpers.c

 drivers/gpu/drm/Makefile                   |   2 +-
 drivers/gpu/drm/drm_flip_work.c            | 124 +++++++++++++++++++++++++++
 drivers/gpu/drm/drm_gem.c                  | 131 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/exynos/exynos_drm_drv.c    |   4 +-
 drivers/gpu/drm/gma500/gtt.c               |  38 ++-------
 drivers/gpu/drm/gma500/psb_drv.c           |   2 +-
 drivers/gpu/drm/i810/i810_dma.c            |   2 +-
 drivers/gpu/drm/i810/i810_drv.h            |   2 +-
 drivers/gpu/drm/i915/i915_dma.c            |   2 +-
 drivers/gpu/drm/i915/i915_drv.h            |   2 +-
 drivers/gpu/drm/mga/mga_drv.h              |   2 +-
 drivers/gpu/drm/mga/mga_state.c            |   2 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c      |   5 +-
 drivers/gpu/drm/omapdrm/Makefile           |   3 -
 drivers/gpu/drm/omapdrm/omap_drv.c         |   2 +-
 drivers/gpu/drm/omapdrm/omap_drv.h         |   5 +-
 drivers/gpu/drm/omapdrm/omap_fb.c          |  74 ++++++++--------
 drivers/gpu/drm/omapdrm/omap_gem.c         |   8 +-
 drivers/gpu/drm/omapdrm/omap_gem_helpers.c | 124 ---------------------------
 drivers/gpu/drm/omapdrm/omap_plane.c       |  51 +++++------
 drivers/gpu/drm/qxl/qxl_drv.h              |   2 +-
 drivers/gpu/drm/qxl/qxl_ioctl.c            |   2 +-
 drivers/gpu/drm/r128/r128_drv.h            |   2 +-
 drivers/gpu/drm/r128/r128_state.c          |   2 +-
 drivers/gpu/drm/radeon/radeon_drv.c        |   2 +-
 drivers/gpu/drm/radeon/radeon_kms.c        |   2 +-
 drivers/gpu/drm/savage/savage_bci.c        |   2 +-
 drivers/gpu/drm/savage/savage_drv.h        |   2 +-
 drivers/gpu/drm/sis/sis_drv.h              |   2 +-
 drivers/gpu/drm/sis/sis_mm.c               |   2 +-
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c       |  33 +++-----
 drivers/gpu/drm/udl/udl_gem.c              |  44 ++--------
 drivers/gpu/drm/via/via_dma.c              |   2 +-
 drivers/gpu/drm/via/via_drv.h              |   2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c        |   4 +-
 drivers/gpu/host1x/drm/drm.c               |   2 +-
 drivers/staging/imx-drm/imx-drm-core.c     |   2 +-
 include/drm/drmP.h                         |   7 +-
 include/drm/drm_flip_work.h                |  71 ++++++++++++++++
 39 files changed, 443 insertions(+), 329 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_flip_work.c
 delete mode 100644 drivers/gpu/drm/omapdrm/omap_gem_helpers.c
 create mode 100644 include/drm/drm_flip_work.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/9] drm: add flip-work helper
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 17:49   ` Daniel Vetter
  2013-08-07 17:41 ` [PATCH 2/9] drm/tilcdc: use " Rob Clark
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

A small helper to queue up work to do, from workqueue context, after a
flip.  Typically useful to defer unreffing buffers that may be read by
the display controller until vblank.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/Makefile        |   2 +-
 drivers/gpu/drm/drm_flip_work.c | 124 ++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_flip_work.h     |  71 +++++++++++++++++++++++
 3 files changed, 196 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_flip_work.c
 create mode 100644 include/drm/drm_flip_work.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index d943b94..2aaf082 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -13,7 +13,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
 		drm_trace_points.o drm_global.o drm_prime.o \
-		drm_rect.o drm_vma_manager.o
+		drm_rect.o drm_vma_manager.o drm_flip_work.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c
new file mode 100644
index 0000000..e788882
--- /dev/null
+++ b/drivers/gpu/drm/drm_flip_work.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_flip_work.h"
+
+/**
+ * drm_flip_work_queue - queue work
+ * @work: the flip-work
+ * @val: the value to queue
+ *
+ * Queues work, that will later be run (passed back to drm_flip_func_t
+ * func) on a work queue after drm_flip_work_commit() is called.
+ */
+void drm_flip_work_queue(struct drm_flip_work *work, void *val)
+{
+	if (kfifo_put(&work->fifo, (const void **)&val)) {
+		atomic_inc(&work->pending);
+	} else {
+		DRM_ERROR("%s fifo full!\n", work->name);
+		work->func(work, val);
+	}
+}
+EXPORT_SYMBOL(drm_flip_work_queue);
+
+/**
+ * drm_flip_work_commit - commit queued work
+ * @work: the flip-work
+ * @wq: the work-queue to run the queued work on
+ *
+ * Trigger work previously queued by drm_flip_work_queue() to run
+ * on a workqueue.  The typical usage would be to queue work (via
+ * drm_flip_work_queue()) at any point (from vblank irq and/or
+ * prior), and then from vblank irq commit the queued work.
+ */
+void drm_flip_work_commit(struct drm_flip_work *work,
+		struct workqueue_struct *wq)
+{
+	uint32_t pending = atomic_read(&work->pending);
+	atomic_add(pending, &work->count);
+	atomic_sub(pending, &work->pending);
+	queue_work(wq, &work->worker);
+}
+EXPORT_SYMBOL(drm_flip_work_commit);
+
+static void flip_worker(struct work_struct *w)
+{
+	struct drm_flip_work *work = container_of(w, struct drm_flip_work, worker);
+	uint32_t count = atomic_read(&work->count);
+	void *val = NULL;
+
+	atomic_sub(count, &work->count);
+
+	while(count--)
+		if (!WARN_ON(!kfifo_get(&work->fifo, &val)))
+			work->func(work, val);
+}
+
+/**
+ * drm_flip_work_init - initialize flip-work
+ * @work: the flip-work to initialize
+ * @size: the max queue depth
+ * @name: debug name
+ * @func: the callback work function
+ *
+ * Initializes/allocates resources for the flip-work
+ *
+ * RETURNS:
+ * Zero on success, error code on failure.
+ */
+int drm_flip_work_init(struct drm_flip_work *work, int size,
+		const char *name, drm_flip_func_t func)
+{
+	int ret;
+
+	work->name = name;
+	atomic_set(&work->count, 0);
+	atomic_set(&work->pending, 0);
+	work->func = func;
+
+	ret = kfifo_alloc(&work->fifo, size, GFP_KERNEL);
+	if (ret) {
+		DRM_ERROR("could not allocate %s fifo\n", name);
+		return ret;
+	}
+
+	INIT_WORK(&work->worker, flip_worker);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_flip_work_init);
+
+/**
+ * drm_flip_work_cleanup - cleans up flip-work
+ * @work: the flip-work to cleanup
+ *
+ * Destroy resources allocated for the flip-work
+ */
+void drm_flip_work_cleanup(struct drm_flip_work *work)
+{
+	WARN_ON(!kfifo_is_empty(&work->fifo));
+	kfifo_free(&work->fifo);
+}
+EXPORT_SYMBOL(drm_flip_work_cleanup);
diff --git a/include/drm/drm_flip_work.h b/include/drm/drm_flip_work.h
new file mode 100644
index 0000000..7d3840b
--- /dev/null
+++ b/include/drm/drm_flip_work.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef DRM_FLIP_WORK_H
+#define DRM_FLIP_WORK_H
+
+#include <linux/kfifo.h>
+#include <linux/workqueue.h>
+
+/**
+ * DOC: flip utils
+ *
+ * Util to queue up work to run from work-queue context after flip/vblank.
+ * Typically this can be used to defer unref of framebuffer's, cursor
+ * bo's, etc until after vblank.  The APIs are all safe (and lockless)
+ * for up to one producer and once consumer at a time.  The single-consumer
+ * aspect is ensured by committing the queued work to a single work-queue.
+ */
+
+struct drm_flip_work;
+
+/**
+ * drm_flip_func_t - callback function
+ *
+ * @work: the flip work
+ * @val: value queued via drm_flip_work_queue()
+ *
+ * Callback function to be called for each of the  queue'd work items after
+ * drm_flip_work_commit() is called.
+ */
+typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);
+
+/**
+ * struct drm_flip_work - flip work queue
+ */
+struct drm_flip_work {
+	const char *name;
+	atomic_t pending, count;
+	drm_flip_func_t func;
+	struct work_struct worker;
+	DECLARE_KFIFO_PTR(fifo, void *);
+};
+
+void drm_flip_work_queue(struct drm_flip_work *work, void *val);
+void drm_flip_work_commit(struct drm_flip_work *work,
+		struct workqueue_struct *wq);
+int drm_flip_work_init(struct drm_flip_work *work, int size,
+		const char *name, drm_flip_func_t func);
+void drm_flip_work_cleanup(struct drm_flip_work *work);
+
+#endif  /* DRM_FLIP_WORK_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/9] drm/tilcdc: use flip-work helper
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
  2013-08-07 17:41 ` [PATCH 1/9] drm: add flip-work helper Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 17:41 ` [PATCH 3/9] drm/omap: " Rob Clark
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Rob Clark <robdclark@gmail.com>
Tested-by: Darren Etheridge <detheridge@ti.com>
---
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 33 ++++++++++++---------------------
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 7418dcd..e09a76e 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -15,7 +15,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/kfifo.h>
+#include "drm_flip_work.h"
 
 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
@@ -35,21 +35,18 @@ struct tilcdc_crtc {
 	struct drm_framebuffer *scanout[2];
 
 	/* for deferred fb unref's: */
-	DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *);
-	struct work_struct work;
+	struct drm_flip_work unref_work;
 };
 #define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
 
-static void unref_worker(struct work_struct *work)
+static void unref_worker(struct drm_flip_work *work, void *val)
 {
 	struct tilcdc_crtc *tilcdc_crtc =
-		container_of(work, struct tilcdc_crtc, work);
+		container_of(work, struct tilcdc_crtc, unref_work);
 	struct drm_device *dev = tilcdc_crtc->base.dev;
-	struct drm_framebuffer *fb;
 
 	mutex_lock(&dev->mode_config.mutex);
-	while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb))
-		drm_framebuffer_unreference(fb);
+	drm_framebuffer_unreference(val);
 	mutex_unlock(&dev->mode_config.mutex);
 }
 
@@ -68,19 +65,14 @@ static void set_scanout(struct drm_crtc *crtc, int n)
 	};
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
 
 	pm_runtime_get_sync(dev->dev);
 	tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
 	tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
 	if (tilcdc_crtc->scanout[n]) {
-		if (kfifo_put(&tilcdc_crtc->unref_fifo,
-				(const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) {
-			struct tilcdc_drm_private *priv = dev->dev_private;
-			queue_work(priv->wq, &tilcdc_crtc->work);
-		} else {
-			dev_err(dev->dev, "unref fifo full!\n");
-			drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
-		}
+		drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]);
+		drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
 	}
 	tilcdc_crtc->scanout[n] = crtc->fb;
 	drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
@@ -149,8 +141,8 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
 	WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
 
 	drm_crtc_cleanup(crtc);
-	WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo));
-	kfifo_free(&tilcdc_crtc->unref_fifo);
+	drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
+
 	kfree(tilcdc_crtc);
 }
 
@@ -666,14 +658,13 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
 	tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
 	init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
 
-	ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL);
+	ret = drm_flip_work_init(&tilcdc_crtc->unref_work, 16,
+			"unref", unref_worker);
 	if (ret) {
 		dev_err(dev->dev, "could not allocate unref FIFO\n");
 		goto fail;
 	}
 
-	INIT_WORK(&tilcdc_crtc->work, unref_worker);
-
 	ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
 	if (ret < 0)
 		goto fail;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/9] drm/omap: use flip-work helper
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
  2013-08-07 17:41 ` [PATCH 1/9] drm: add flip-work helper Rob Clark
  2013-08-07 17:41 ` [PATCH 2/9] drm/tilcdc: use " Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 17:41 ` [PATCH 4/9] drm: const'ify ioctls table (v2) Rob Clark
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

And simplify how we hold a ref+pin to what is being scanned out by using
fb refcnt'ing.  The previous logic pre-dated fb refcnt, and as a result
was less straightforward than it could have been.  By holding a ref to
the fb, we don't have to care about how many plane's there are and
holding a ref to each color plane's bo.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/omapdrm/omap_drv.h   |  5 +--
 drivers/gpu/drm/omapdrm/omap_fb.c    | 74 +++++++++++++++++-------------------
 drivers/gpu/drm/omapdrm/omap_plane.c | 51 +++++++++++--------------
 3 files changed, 58 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 14f17da..29ac584 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -203,9 +203,8 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
-int omap_framebuffer_replace(struct drm_framebuffer *a,
-		struct drm_framebuffer *b, void *arg,
-		void (*unpin)(void *arg, struct drm_gem_object *bo));
+int omap_framebuffer_pin(struct drm_framebuffer *fb);
+int omap_framebuffer_unpin(struct drm_framebuffer *fb);
 void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 		struct omap_drm_window *win, struct omap_overlay_info *info);
 struct drm_connector *omap_framebuffer_get_next_connector(
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 8031402..f2b8f06 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -237,55 +237,49 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
 	}
 }
 
-/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL).  Although
- * buffers to unpin are just pushed to the unpin fifo so that the
- * caller can defer unpin until vblank.
- *
- * Note if this fails (ie. something went very wrong!), all buffers are
- * unpinned, and the caller disables the overlay.  We could have tried
- * to revert back to the previous set of pinned buffers but if things are
- * hosed there is no guarantee that would succeed.
- */
-int omap_framebuffer_replace(struct drm_framebuffer *a,
-		struct drm_framebuffer *b, void *arg,
-		void (*unpin)(void *arg, struct drm_gem_object *bo))
+/* pin, prepare for scanout: */
+int omap_framebuffer_pin(struct drm_framebuffer *fb)
 {
-	int ret = 0, i, na, nb;
-	struct omap_framebuffer *ofba = to_omap_framebuffer(a);
-	struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
-	uint32_t pinned_mask = 0;
+	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+	int ret, i, n = drm_format_num_planes(fb->pixel_format);
 
-	na = a ? drm_format_num_planes(a->pixel_format) : 0;
-	nb = b ? drm_format_num_planes(b->pixel_format) : 0;
+	for (i = 0; i < n; i++) {
+		struct plane *plane = &omap_fb->planes[i];
+		ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
+		if (ret)
+			goto fail;
+		omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE);
+	}
 
-	for (i = 0; i < max(na, nb); i++) {
-		struct plane *pa, *pb;
+	return 0;
 
-		pa = (i < na) ? &ofba->planes[i] : NULL;
-		pb = (i < nb) ? &ofbb->planes[i] : NULL;
+fail:
+	for (i--; i >= 0; i--) {
+		struct plane *plane = &omap_fb->planes[i];
+		omap_gem_put_paddr(plane->bo);
+		plane->paddr = 0;
+	}
 
-		if (pa)
-			unpin(arg, pa->bo);
+	return ret;
+}
 
-		if (pb && !ret) {
-			ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
-			if (!ret) {
-				omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE);
-				pinned_mask |= (1 << i);
-			}
-		}
-	}
+/* unpin, no longer being scanned out: */
+int omap_framebuffer_unpin(struct drm_framebuffer *fb)
+{
+	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+	int ret, i, n = drm_format_num_planes(fb->pixel_format);
 
-	if (ret) {
-		/* something went wrong.. unpin what has been pinned */
-		for (i = 0; i < nb; i++) {
-			if (pinned_mask & (1 << i)) {
-				struct plane *pb = &ofba->planes[i];
-				unpin(arg, pb->bo);
-			}
-		}
+	for (i = 0; i < n; i++) {
+		struct plane *plane = &omap_fb->planes[i];
+		ret = omap_gem_put_paddr(plane->bo);
+		if (ret)
+			goto fail;
+		plane->paddr = 0;
 	}
 
+	return 0;
+
+fail:
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 8d225d7..046d5e6 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -17,7 +17,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/kfifo.h>
+#include "drm_flip_work.h"
 
 #include "omap_drv.h"
 #include "omap_dmm_tiler.h"
@@ -58,26 +58,23 @@ struct omap_plane {
 
 	struct omap_drm_irq error_irq;
 
-	/* set of bo's pending unpin until next post_apply() */
-	DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *);
+	/* for deferring bo unpin's until next post_apply(): */
+	struct drm_flip_work unpin_work;
 
 	// XXX maybe get rid of this and handle vblank in crtc too?
 	struct callback apply_done_cb;
 };
 
-static void unpin(void *arg, struct drm_gem_object *bo)
+static void unpin_worker(struct drm_flip_work *work, void *val)
 {
-	struct drm_plane *plane = arg;
-	struct omap_plane *omap_plane = to_omap_plane(plane);
+	struct omap_plane *omap_plane =
+			container_of(work, struct omap_plane, unpin_work);
+	struct drm_device *dev = omap_plane->base.dev;
 
-	if (kfifo_put(&omap_plane->unpin_fifo,
-			(const struct drm_gem_object **)&bo)) {
-		/* also hold a ref so it isn't free'd while pinned */
-		drm_gem_object_reference(bo);
-	} else {
-		dev_err(plane->dev->dev, "unpin fifo full!\n");
-		omap_gem_put_paddr(bo);
-	}
+	omap_framebuffer_unpin(val);
+	mutex_lock(&dev->mode_config.mutex);
+	drm_framebuffer_unreference(val);
+	mutex_unlock(&dev->mode_config.mutex);
 }
 
 /* update which fb (if any) is pinned for scanout */
@@ -87,23 +84,22 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
 	struct drm_framebuffer *pinned_fb = omap_plane->pinned_fb;
 
 	if (pinned_fb != fb) {
-		int ret;
+		int ret = 0;
 
 		DBG("%p -> %p", pinned_fb, fb);
 
-		if (fb)
+		if (fb) {
 			drm_framebuffer_reference(fb);
-
-		ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin);
+			ret = omap_framebuffer_pin(fb);
+		}
 
 		if (pinned_fb)
-			drm_framebuffer_unreference(pinned_fb);
+			drm_flip_work_queue(&omap_plane->unpin_work, pinned_fb);
 
 		if (ret) {
 			dev_err(plane->dev->dev, "could not swap %p -> %p\n",
 					omap_plane->pinned_fb, fb);
-			if (fb)
-				drm_framebuffer_unreference(fb);
+			drm_framebuffer_unreference(fb);
 			omap_plane->pinned_fb = NULL;
 			return ret;
 		}
@@ -170,17 +166,14 @@ static void omap_plane_post_apply(struct omap_drm_apply *apply)
 	struct omap_plane *omap_plane =
 			container_of(apply, struct omap_plane, apply);
 	struct drm_plane *plane = &omap_plane->base;
+	struct omap_drm_private *priv = plane->dev->dev_private;
 	struct omap_overlay_info *info = &omap_plane->info;
-	struct drm_gem_object *bo = NULL;
 	struct callback cb;
 
 	cb = omap_plane->apply_done_cb;
 	omap_plane->apply_done_cb.fxn = NULL;
 
-	while (kfifo_get(&omap_plane->unpin_fifo, &bo)) {
-		omap_gem_put_paddr(bo);
-		drm_gem_object_unreference_unlocked(bo);
-	}
+	drm_flip_work_commit(&omap_plane->unpin_work, priv->wq);
 
 	if (cb.fxn)
 		cb.fxn(cb.arg);
@@ -277,8 +270,7 @@ static void omap_plane_destroy(struct drm_plane *plane)
 	omap_plane_disable(plane);
 	drm_plane_cleanup(plane);
 
-	WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo));
-	kfifo_free(&omap_plane->unpin_fifo);
+	drm_flip_work_cleanup(&omap_plane->unpin_work);
 
 	kfree(omap_plane);
 }
@@ -399,7 +391,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
 	if (!omap_plane)
 		goto fail;
 
-	ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
+	ret = drm_flip_work_init(&omap_plane->unpin_work, 16,
+			"unpin", unpin_worker);
 	if (ret) {
 		dev_err(dev->dev, "could not allocate unpin FIFO\n");
 		goto fail;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/9] drm: const'ify ioctls table (v2)
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
                   ` (2 preceding siblings ...)
  2013-08-07 17:41 ` [PATCH 3/9] drm/omap: " Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 17:48   ` Rob Clark
  2013-08-07 17:41 ` [PATCH 5/9] drm/gem: add drm_gem_create_mmap_offset_size() Rob Clark
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Because, there is no reason for it not to be const.

v1: original
v2: fix compile break in vmwgfx, and couple related cleanups suggested
    by Ville Syrjälä

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/exynos/exynos_drm_drv.c | 4 ++--
 drivers/gpu/drm/gma500/psb_drv.c        | 2 +-
 drivers/gpu/drm/i810/i810_dma.c         | 2 +-
 drivers/gpu/drm/i810/i810_drv.h         | 2 +-
 drivers/gpu/drm/i915/i915_dma.c         | 2 +-
 drivers/gpu/drm/i915/i915_drv.h         | 2 +-
 drivers/gpu/drm/mga/mga_drv.h           | 2 +-
 drivers/gpu/drm/mga/mga_state.c         | 2 +-
 drivers/gpu/drm/nouveau/nouveau_drm.c   | 5 ++---
 drivers/gpu/drm/omapdrm/omap_drv.c      | 2 +-
 drivers/gpu/drm/qxl/qxl_drv.h           | 2 +-
 drivers/gpu/drm/qxl/qxl_ioctl.c         | 2 +-
 drivers/gpu/drm/r128/r128_drv.h         | 2 +-
 drivers/gpu/drm/r128/r128_state.c       | 2 +-
 drivers/gpu/drm/radeon/radeon_drv.c     | 2 +-
 drivers/gpu/drm/radeon/radeon_kms.c     | 2 +-
 drivers/gpu/drm/savage/savage_bci.c     | 2 +-
 drivers/gpu/drm/savage/savage_drv.h     | 2 +-
 drivers/gpu/drm/sis/sis_drv.h           | 2 +-
 drivers/gpu/drm/sis/sis_mm.c            | 2 +-
 drivers/gpu/drm/via/via_dma.c           | 2 +-
 drivers/gpu/drm/via/via_drv.h           | 2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c     | 4 ++--
 drivers/gpu/host1x/drm/drm.c            | 2 +-
 drivers/staging/imx-drm/imx-drm-core.c  | 2 +-
 include/drm/drmP.h                      | 2 +-
 26 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index ca2729a..7b9c879 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -213,7 +213,7 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
 	.close = drm_gem_vm_close,
 };
 
-static struct drm_ioctl_desc exynos_ioctls[] = {
+static const struct drm_ioctl_desc exynos_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl,
 			DRM_UNLOCKED | DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET,
@@ -277,6 +277,7 @@ static struct drm_driver exynos_drm_driver = {
 	.gem_prime_export	= exynos_dmabuf_prime_export,
 	.gem_prime_import	= exynos_dmabuf_prime_import,
 	.ioctls			= exynos_ioctls,
+	.num_ioctls		= ARRAY_SIZE(exynos_ioctls),
 	.fops			= &exynos_drm_driver_fops,
 	.name	= DRIVER_NAME,
 	.desc	= DRIVER_DESC,
@@ -288,7 +289,6 @@ static struct drm_driver exynos_drm_driver = {
 static int exynos_drm_platform_probe(struct platform_device *pdev)
 {
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-	exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
 
 	return drm_platform_init(&exynos_drm_driver, pdev);
 }
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index bddea58..ffc9e25 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -131,7 +131,7 @@ static int psb_gamma_ioctl(struct drm_device *dev, void *data,
 static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
 			     struct drm_file *file_priv);
 
-static struct drm_ioctl_desc psb_ioctls[] = {
+static const struct drm_ioctl_desc psb_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl,
 		      DRM_AUTH),
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index ada49ed..eac755b 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -1241,7 +1241,7 @@ int i810_driver_dma_quiescent(struct drm_device *dev)
 	return 0;
 }
 
-struct drm_ioctl_desc i810_ioctls[] = {
+const struct drm_ioctl_desc i810_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h
index 6e0acad..d4d16ed 100644
--- a/drivers/gpu/drm/i810/i810_drv.h
+++ b/drivers/gpu/drm/i810/i810_drv.h
@@ -125,7 +125,7 @@ extern void i810_driver_preclose(struct drm_device *dev,
 extern int i810_driver_device_is_agp(struct drm_device *dev);
 
 extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-extern struct drm_ioctl_desc i810_ioctls[];
+extern const struct drm_ioctl_desc i810_ioctls[];
 extern int i810_max_ioctl;
 
 #define I810_BASE(reg)		((unsigned long) \
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 6ce9033..78ad4dc 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1834,7 +1834,7 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
 	kfree(file_priv);
 }
 
-struct drm_ioctl_desc i915_ioctls[] = {
+const struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(I915_FLIP, i915_flip_bufs, DRM_AUTH),
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cef35d3..37d8c92 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1566,7 +1566,7 @@ struct drm_i915_file_private {
 #define INTEL_RC6p_ENABLE			(1<<1)
 #define INTEL_RC6pp_ENABLE			(1<<2)
 
-extern struct drm_ioctl_desc i915_ioctls[];
+extern const struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc __always_unused;
 extern int i915_panel_ignore_lid __read_mostly;
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
index 54558a0..ca4bc54 100644
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -149,7 +149,7 @@ typedef struct drm_mga_private {
 	unsigned int agp_size;
 } drm_mga_private_t;
 
-extern struct drm_ioctl_desc mga_ioctls[];
+extern const struct drm_ioctl_desc mga_ioctls[];
 extern int mga_max_ioctl;
 
 				/* mga_dma.c */
diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c
index 9c14514..37cc2fb 100644
--- a/drivers/gpu/drm/mga/mga_state.c
+++ b/drivers/gpu/drm/mga/mga_state.c
@@ -1083,7 +1083,7 @@ file_priv)
 	return 0;
 }
 
-struct drm_ioctl_desc mga_ioctls[] = {
+const struct drm_ioctl_desc mga_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH),
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index e990327..bcd0199 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -640,7 +640,7 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
 	nouveau_cli_destroy(cli);
 }
 
-static struct drm_ioctl_desc
+static const struct drm_ioctl_desc
 nouveau_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -695,6 +695,7 @@ driver = {
 	.disable_vblank = nouveau_drm_vblank_disable,
 
 	.ioctls = nouveau_ioctls,
+	.num_ioctls = ARRAY_SIZE(nouveau_ioctls),
 	.fops = &nouveau_driver_fops,
 
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
@@ -765,8 +766,6 @@ nouveau_drm_pci_driver = {
 static int __init
 nouveau_drm_init(void)
 {
-	driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls);
-
 	if (nouveau_modeset == -1) {
 #ifdef CONFIG_VGA_CONSOLE
 		if (vgacon_text_force())
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index a3004f1..22a9a5f 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -419,7 +419,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
 	return ret;
 }
 
-static struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
+static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
 	DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index aacb791..bb489c4 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -319,7 +319,7 @@ struct qxl_device {
 /* forward declaration for QXL_INFO_IO */
 void qxl_io_log(struct qxl_device *qdev, const char *fmt, ...);
 
-extern struct drm_ioctl_desc qxl_ioctls[];
+extern const struct drm_ioctl_desc qxl_ioctls[];
 extern int qxl_max_ioctl;
 
 int qxl_driver_load(struct drm_device *dev, unsigned long flags);
diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c
index 27f45e4..6cd7273 100644
--- a/drivers/gpu/drm/qxl/qxl_ioctl.c
+++ b/drivers/gpu/drm/qxl/qxl_ioctl.c
@@ -402,7 +402,7 @@ static int qxl_alloc_surf_ioctl(struct drm_device *dev, void *data,
 	return ret;
 }
 
-struct drm_ioctl_desc qxl_ioctls[] = {
+const struct drm_ioctl_desc qxl_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(QXL_ALLOC, qxl_alloc_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
 	DRM_IOCTL_DEF_DRV(QXL_MAP, qxl_map_ioctl, DRM_AUTH|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 930c71b..56eb5e3 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -131,7 +131,7 @@ typedef struct drm_r128_buf_priv {
 	drm_r128_freelist_t *list_entry;
 } drm_r128_buf_priv_t;
 
-extern struct drm_ioctl_desc r128_ioctls[];
+extern const struct drm_ioctl_desc r128_ioctls[];
 extern int r128_max_ioctl;
 
 				/* r128_cce.c */
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 19bb7e6..01dd9ae 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1643,7 +1643,7 @@ void r128_driver_lastclose(struct drm_device *dev)
 	r128_do_cleanup_cce(dev);
 }
 
-struct drm_ioctl_desc r128_ioctls[] = {
+const struct drm_ioctl_desc r128_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index cb7f1a8..e2df2e9 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -109,7 +109,7 @@ void radeon_gem_object_close(struct drm_gem_object *obj,
 				struct drm_file *file_priv);
 extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
 				      int *vpos, int *hpos);
-extern struct drm_ioctl_desc radeon_ioctls_kms[];
+extern const struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
 int radeon_mode_dumb_mmap(struct drm_file *filp,
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 07b0236..866c2b7 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -722,7 +722,7 @@ KMS_INVALID_IOCTL(radeon_surface_alloc_kms)
 KMS_INVALID_IOCTL(radeon_surface_free_kms)
 
 
-struct drm_ioctl_desc radeon_ioctls_kms[] = {
+const struct drm_ioctl_desc radeon_ioctls_kms[] = {
 	DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
index bd6b2cf..b17d071 100644
--- a/drivers/gpu/drm/savage/savage_bci.c
+++ b/drivers/gpu/drm/savage/savage_bci.c
@@ -1072,7 +1072,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
 		drm_idlelock_release(&file_priv->master->lock);
 }
 
-struct drm_ioctl_desc savage_ioctls[] = {
+const struct drm_ioctl_desc savage_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF_DRV(SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
diff --git a/drivers/gpu/drm/savage/savage_drv.h b/drivers/gpu/drm/savage/savage_drv.h
index c05082a..335f8fc 100644
--- a/drivers/gpu/drm/savage/savage_drv.h
+++ b/drivers/gpu/drm/savage/savage_drv.h
@@ -104,7 +104,7 @@ enum savage_family {
 	S3_LAST
 };
 
-extern struct drm_ioctl_desc savage_ioctls[];
+extern const struct drm_ioctl_desc savage_ioctls[];
 extern int savage_max_ioctl;
 
 #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
index 13b527b..c31c025 100644
--- a/drivers/gpu/drm/sis/sis_drv.h
+++ b/drivers/gpu/drm/sis/sis_drv.h
@@ -70,7 +70,7 @@ extern void sis_reclaim_buffers_locked(struct drm_device *dev,
 				       struct drm_file *file_priv);
 extern void sis_lastclose(struct drm_device *dev);
 
-extern struct drm_ioctl_desc sis_ioctls[];
+extern const struct drm_ioctl_desc sis_ioctls[];
 extern int sis_max_ioctl;
 
 #endif
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index 9a43d98..0f8b7eb 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -348,7 +348,7 @@ void sis_reclaim_buffers_locked(struct drm_device *dev,
 	return;
 }
 
-struct drm_ioctl_desc sis_ioctls[] = {
+const struct drm_ioctl_desc sis_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c
index 13558f5..652f9b4 100644
--- a/drivers/gpu/drm/via/via_dma.c
+++ b/drivers/gpu/drm/via/via_dma.c
@@ -720,7 +720,7 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *
 	return ret;
 }
 
-struct drm_ioctl_desc via_ioctls[] = {
+const struct drm_ioctl_desc via_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 893a650..a811ef2 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -114,7 +114,7 @@ enum via_family {
 #define VIA_READ8(reg)		DRM_READ8(VIA_BASE, reg)
 #define VIA_WRITE8(reg, val)	DRM_WRITE8(VIA_BASE, reg, val)
 
-extern struct drm_ioctl_desc via_ioctls[];
+extern const struct drm_ioctl_desc via_ioctls[];
 extern int via_max_ioctl;
 
 extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 78e2164..5086150 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -124,7 +124,7 @@
  * Ioctl definitions.
  */
 
-static struct drm_ioctl_desc vmw_ioctls[] = {
+static const struct drm_ioctl_desc vmw_ioctls[] = {
 	VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
 		      DRM_AUTH | DRM_UNLOCKED),
 	VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
@@ -782,7 +782,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
 
 	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
 	    && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
-		struct drm_ioctl_desc *ioctl =
+		const struct drm_ioctl_desc *ioctl =
 		    &vmw_ioctls[nr - DRM_COMMAND_BASE];
 
 		if (unlikely(ioctl->cmd_drv != cmd)) {
diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c
index e184b00..7a3c9f2 100644
--- a/drivers/gpu/host1x/drm/drm.c
+++ b/drivers/gpu/host1x/drm/drm.c
@@ -487,7 +487,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
 }
 #endif
 
-static struct drm_ioctl_desc tegra_drm_ioctls[] = {
+static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
 #ifdef CONFIG_DRM_TEGRA_STAGING
 	DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
 	DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 9854a1d..9610229 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -783,7 +783,7 @@ int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
 }
 EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
 
-static struct drm_ioctl_desc imx_drm_ioctls[] = {
+static const struct drm_ioctl_desc imx_drm_ioctls[] = {
 	/* none so far */
 };
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 4b518e0..1cc765a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -965,7 +965,7 @@ struct drm_driver {
 
 	u32 driver_features;
 	int dev_priv_size;
-	struct drm_ioctl_desc *ioctls;
+	const struct drm_ioctl_desc *ioctls;
 	int num_ioctls;
 	const struct file_operations *fops;
 	union {
-- 
1.8.3.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 5/9] drm/gem: add drm_gem_create_mmap_offset_size()
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
                   ` (3 preceding siblings ...)
  2013-08-07 17:41 ` [PATCH 4/9] drm: const'ify ioctls table (v2) Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-08 15:29   ` David Herrmann
  2013-08-07 17:41 ` [PATCH 6/9] drm/gem: add shmem get/put page helpers Rob Clark
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Variant of drm_gem_create_mmap_offset() which doesn't make the
assumption that virtual size and physical size (obj->size) are the same.
This is needed in omapdrm to deal with tiled buffers.  And lets us get
rid of a duplicated and slightly modified version of
drm_gem_create_mmap_offset() in omapdrm.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/drm_gem.c | 28 ++++++++++++++++++++++++----
 include/drm/drmP.h        |  1 +
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 1f76572..84d59f7 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -303,24 +303,44 @@ drm_gem_free_mmap_offset(struct drm_gem_object *obj)
 EXPORT_SYMBOL(drm_gem_free_mmap_offset);
 
 /**
- * drm_gem_create_mmap_offset - create a fake mmap offset for an object
+ * drm_gem_create_mmap_offset_size - create a fake mmap offset for an object
  * @obj: obj in question
+ * @size: the virtual size
  *
  * GEM memory mapping works by handing back to userspace a fake mmap offset
  * it can use in a subsequent mmap(2) call.  The DRM core code then looks
  * up the object based on the offset and sets up the various memory mapping
  * structures.
  *
- * This routine allocates and attaches a fake offset for @obj.
+ * This routine allocates and attaches a fake offset for @obj, in cases where
+ * the virtual size differs from the physical size (ie. obj->size).  Otherwise
+ * just use drm_gem_create_mmap_offset().
  */
 int
-drm_gem_create_mmap_offset(struct drm_gem_object *obj)
+drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_gem_mm *mm = dev->mm_private;
 
 	return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
-				  obj->size / PAGE_SIZE);
+				  size / PAGE_SIZE);
+}
+EXPORT_SYMBOL(drm_gem_create_mmap_offset_size);
+
+/**
+ * drm_gem_create_mmap_offset - create a fake mmap offset for an object
+ * @obj: obj in question
+ *
+ * GEM memory mapping works by handing back to userspace a fake mmap offset
+ * it can use in a subsequent mmap(2) call.  The DRM core code then looks
+ * up the object based on the offset and sets up the various memory mapping
+ * structures.
+ *
+ * This routine allocates and attaches a fake offset for @obj.
+ */
+int drm_gem_create_mmap_offset(struct drm_gem_object *obj)
+{
+	return drm_gem_create_mmap_offset_size(obj, obj->size);
 }
 EXPORT_SYMBOL(drm_gem_create_mmap_offset);
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 1cc765a..d00eb89 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1668,6 +1668,7 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
 
 void drm_gem_free_mmap_offset(struct drm_gem_object *obj);
 int drm_gem_create_mmap_offset(struct drm_gem_object *obj);
+int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
 
 struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
 					     struct drm_file *filp,
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 6/9] drm/gem: add shmem get/put page helpers
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
                   ` (4 preceding siblings ...)
  2013-08-07 17:41 ` [PATCH 5/9] drm/gem: add drm_gem_create_mmap_offset_size() Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 17:41 ` [PATCH 7/9] drm/gma500: use gem " Rob Clark
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Basically just extracting some code duplicated in gma500, omapdrm, udl,
and upcoming msm driver.

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/drm_gem.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drmP.h        |   4 ++
 2 files changed, 107 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 84d59f7..4355e3e 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -344,6 +344,109 @@ int drm_gem_create_mmap_offset(struct drm_gem_object *obj)
 }
 EXPORT_SYMBOL(drm_gem_create_mmap_offset);
 
+/**
+ * drm_gem_get_pages - helper to allocate backing pages for a GEM object
+ * from shmem
+ * @obj: obj in question
+ * @gfpmask: gfp mask of requested pages
+ */
+struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
+{
+	struct inode *inode;
+	struct address_space *mapping;
+	struct page *p, **pages;
+	int i, npages;
+
+	/* This is the shared memory object that backs the GEM resource */
+	inode = file_inode(obj->filp);
+	mapping = inode->i_mapping;
+
+	/* We already BUG_ON() for non-page-aligned sizes in
+	 * drm_gem_object_init(), so we should never hit this unless
+	 * driver author is doing something really wrong:
+	 */
+	WARN_ON((obj->size & (PAGE_SIZE - 1)) != 0);
+
+	npages = obj->size >> PAGE_SHIFT;
+
+	pages = drm_malloc_ab(npages, sizeof(struct page *));
+	if (pages == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	gfpmask |= mapping_gfp_mask(mapping);
+
+	for (i = 0; i < npages; i++) {
+		p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
+		if (IS_ERR(p))
+			goto fail;
+		pages[i] = p;
+
+		/* There is a hypothetical issue w/ drivers that require
+		 * buffer memory in the low 4GB.. if the pages are un-
+		 * pinned, and swapped out, they can end up swapped back
+		 * in above 4GB.  If pages are already in memory, then
+		 * shmem_read_mapping_page_gfp will ignore the gfpmask,
+		 * even if the already in-memory page disobeys the mask.
+		 *
+		 * It is only a theoretical issue today, because none of
+		 * the devices with this limitation can be populated with
+		 * enough memory to trigger the issue.  But this BUG_ON()
+		 * is here as a reminder in case the problem with
+		 * shmem_read_mapping_page_gfp() isn't solved by the time
+		 * it does become a real issue.
+		 *
+		 * See this thread: http://lkml.org/lkml/2011/7/11/238
+		 */
+		BUG_ON((gfpmask & __GFP_DMA32) &&
+				(page_to_pfn(p) >= 0x00100000UL));
+	}
+
+	return pages;
+
+fail:
+	while (i--)
+		page_cache_release(pages[i]);
+
+	drm_free_large(pages);
+	return ERR_CAST(p);
+}
+EXPORT_SYMBOL(drm_gem_get_pages);
+
+/**
+ * drm_gem_put_pages - helper to free backing pages for a GEM object
+ * @obj: obj in question
+ * @pages: pages to free
+ * @dirty: if true, pages will be marked as dirty
+ * @accessed: if true, the pages will be marked as accessed
+ */
+void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
+		bool dirty, bool accessed)
+{
+	int i, npages;
+
+	/* We already BUG_ON() for non-page-aligned sizes in
+	 * drm_gem_object_init(), so we should never hit this unless
+	 * driver author is doing something really wrong:
+	 */
+	WARN_ON((obj->size & (PAGE_SIZE - 1)) != 0);
+
+	npages = obj->size >> PAGE_SHIFT;
+
+	for (i = 0; i < npages; i++) {
+		if (dirty)
+			set_page_dirty(pages[i]);
+
+		if (accessed)
+			mark_page_accessed(pages[i]);
+
+		/* Undo the reference we took when populating the table */
+		page_cache_release(pages[i]);
+	}
+
+	drm_free_large(pages);
+}
+EXPORT_SYMBOL(drm_gem_put_pages);
+
 /** Returns a reference to the object named by the handle. */
 struct drm_gem_object *
 drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index d00eb89..0045195 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1670,6 +1670,10 @@ void drm_gem_free_mmap_offset(struct drm_gem_object *obj);
 int drm_gem_create_mmap_offset(struct drm_gem_object *obj);
 int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
 
+struct page **drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
+void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
+		bool dirty, bool accessed);
+
 struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
 					     struct drm_file *filp,
 					     u32 handle);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 7/9] drm/gma500: use gem get/put page helpers
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
                   ` (5 preceding siblings ...)
  2013-08-07 17:41 ` [PATCH 6/9] drm/gem: add shmem get/put page helpers Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-10-08 19:57   ` Guillaume CLÉMENT
  2013-08-07 17:41 ` [PATCH 8/9] drm/udl: " Rob Clark
  2013-08-07 17:41 ` [PATCH 9/9] drm/omap: kill omap_gem_helpers.c Rob Clark
  8 siblings, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/gma500/gtt.c | 38 ++++++--------------------------------
 1 file changed, 6 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 1f82183..92babac 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -196,37 +196,17 @@ void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
  */
 static int psb_gtt_attach_pages(struct gtt_range *gt)
 {
-	struct inode *inode;
-	struct address_space *mapping;
-	int i;
-	struct page *p;
-	int pages = gt->gem.size / PAGE_SIZE;
+	struct page **pages;
 
 	WARN_ON(gt->pages);
 
-	/* This is the shared memory object that backs the GEM resource */
-	inode = file_inode(gt->gem.filp);
-	mapping = inode->i_mapping;
+	pages = drm_gem_get_pages(&gt->gem, 0);
+	if (IS_ERR(pages))
+		return PTR_ERR(pages);
 
-	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
-	if (gt->pages == NULL)
-		return -ENOMEM;
-	gt->npage = pages;
+	gt->pages = pages;
 
-	for (i = 0; i < pages; i++) {
-		p = shmem_read_mapping_page(mapping, i);
-		if (IS_ERR(p))
-			goto err;
-		gt->pages[i] = p;
-	}
 	return 0;
-
-err:
-	while (i--)
-		page_cache_release(gt->pages[i]);
-	kfree(gt->pages);
-	gt->pages = NULL;
-	return PTR_ERR(p);
 }
 
 /**
@@ -240,13 +220,7 @@ err:
  */
 static void psb_gtt_detach_pages(struct gtt_range *gt)
 {
-	int i;
-	for (i = 0; i < gt->npage; i++) {
-		/* FIXME: do we need to force dirty */
-		set_page_dirty(gt->pages[i]);
-		page_cache_release(gt->pages[i]);
-	}
-	kfree(gt->pages);
+	drm_gem_put_pages(&gt->gem, gt->pages, true, false);
 	gt->pages = NULL;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 8/9] drm/udl: use gem get/put page helpers
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
                   ` (6 preceding siblings ...)
  2013-08-07 17:41 ` [PATCH 7/9] drm/gma500: use gem " Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 17:41 ` [PATCH 9/9] drm/omap: kill omap_gem_helpers.c Rob Clark
  8 siblings, 0 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/udl/udl_gem.c | 44 ++++++-------------------------------------
 1 file changed, 6 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index 2a4cb2f..8ea3f8f 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -123,55 +123,23 @@ int udl_gem_init_object(struct drm_gem_object *obj)
 
 static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask)
 {
-	int page_count, i;
-	struct page *page;
-	struct inode *inode;
-	struct address_space *mapping;
+	struct page **pages;
 
 	if (obj->pages)
 		return 0;
 
-	page_count = obj->base.size / PAGE_SIZE;
-	BUG_ON(obj->pages != NULL);
-	obj->pages = drm_malloc_ab(page_count, sizeof(struct page *));
-	if (obj->pages == NULL)
-		return -ENOMEM;
-
-	inode = file_inode(obj->base.filp);
-	mapping = inode->i_mapping;
-	gfpmask |= mapping_gfp_mask(mapping);
+	pages = drm_gem_get_pages(&obj->base, gfpmask);
+	if (IS_ERR(pages))
+		return PTR_ERR(pages);
 
-	for (i = 0; i < page_count; i++) {
-		page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
-		if (IS_ERR(page))
-			goto err_pages;
-		obj->pages[i] = page;
-	}
+	obj->pages = pages;
 
 	return 0;
-err_pages:
-	while (i--)
-		page_cache_release(obj->pages[i]);
-	drm_free_large(obj->pages);
-	obj->pages = NULL;
-	return PTR_ERR(page);
 }
 
 static void udl_gem_put_pages(struct udl_gem_object *obj)
 {
-	int page_count = obj->base.size / PAGE_SIZE;
-	int i;
-
-	if (obj->base.import_attach) {
-		drm_free_large(obj->pages);
-		obj->pages = NULL;
-		return;
-	}
-
-	for (i = 0; i < page_count; i++)
-		page_cache_release(obj->pages[i]);
-
-	drm_free_large(obj->pages);
+	drm_gem_put_pages(&obj->base, obj->pages, false, false);
 	obj->pages = NULL;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 9/9] drm/omap: kill omap_gem_helpers.c
  2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
                   ` (7 preceding siblings ...)
  2013-08-07 17:41 ` [PATCH 8/9] drm/udl: " Rob Clark
@ 2013-08-07 17:41 ` Rob Clark
  2013-08-07 20:13   ` Daniel Vetter
  8 siblings, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:41 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Rob Clark <robdclark@gmail.com>
---
 drivers/gpu/drm/omapdrm/Makefile           |   3 -
 drivers/gpu/drm/omapdrm/omap_gem.c         |   8 +-
 drivers/gpu/drm/omapdrm/omap_gem_helpers.c | 124 -----------------------------
 3 files changed, 4 insertions(+), 131 deletions(-)
 delete mode 100644 drivers/gpu/drm/omapdrm/omap_gem_helpers.c

diff --git a/drivers/gpu/drm/omapdrm/Makefile b/drivers/gpu/drm/omapdrm/Makefile
index d85e058..778372b 100644
--- a/drivers/gpu/drm/omapdrm/Makefile
+++ b/drivers/gpu/drm/omapdrm/Makefile
@@ -18,7 +18,4 @@ omapdrm-y := omap_drv.o \
 	omap_dmm_tiler.o \
 	tcm-sita.o
 
-# temporary:
-omapdrm-y += omap_gem_helpers.o
-
 obj-$(CONFIG_DRM_OMAP)	+= omapdrm.o
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index f90531fc00..030af5a 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -237,7 +237,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
 	 * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
 	 * we actually want CMA memory for it all anyways..
 	 */
-	pages = _drm_gem_get_pages(obj, GFP_KERNEL);
+	pages = drm_gem_get_pages(obj, GFP_KERNEL);
 	if (IS_ERR(pages)) {
 		dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages));
 		return PTR_ERR(pages);
@@ -271,7 +271,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
 	return 0;
 
 free_pages:
-	_drm_gem_put_pages(obj, pages, true, false);
+	drm_gem_put_pages(obj, pages, true, false);
 
 	return ret;
 }
@@ -295,7 +295,7 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
 	kfree(omap_obj->addrs);
 	omap_obj->addrs = NULL;
 
-	_drm_gem_put_pages(obj, omap_obj->pages, true, false);
+	drm_gem_put_pages(obj, omap_obj->pages, true, false);
 	omap_obj->pages = NULL;
 }
 
@@ -316,7 +316,7 @@ static uint64_t mmap_offset(struct drm_gem_object *obj)
 
 	/* Make it mmapable */
 	size = omap_gem_mmap_size(obj);
-	ret = _drm_gem_create_mmap_offset_size(obj, size);
+	ret = drm_gem_create_mmap_offset_size(obj, size);
 	if (ret) {
 		dev_err(dev->dev, "could not allocate mmap offset\n");
 		return 0;
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c b/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
deleted file mode 100644
index dbb1575..0000000
--- a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * drivers/gpu/drm/omapdrm/omap_gem_helpers.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* temporary copy of drm_gem_{get,put}_pages() until the
- * "drm/gem: add functions to get/put pages" patch is merged..
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/shmem_fs.h>
-
-#include <drm/drmP.h>
-
-/**
- * drm_gem_get_pages - helper to allocate backing pages for a GEM object
- * @obj: obj in question
- * @gfpmask: gfp mask of requested pages
- */
-struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
-{
-	struct inode *inode;
-	struct address_space *mapping;
-	struct page *p, **pages;
-	int i, npages;
-
-	/* This is the shared memory object that backs the GEM resource */
-	inode = file_inode(obj->filp);
-	mapping = inode->i_mapping;
-
-	npages = obj->size >> PAGE_SHIFT;
-
-	pages = drm_malloc_ab(npages, sizeof(struct page *));
-	if (pages == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	gfpmask |= mapping_gfp_mask(mapping);
-
-	for (i = 0; i < npages; i++) {
-		p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
-		if (IS_ERR(p))
-			goto fail;
-		pages[i] = p;
-
-		/* There is a hypothetical issue w/ drivers that require
-		 * buffer memory in the low 4GB.. if the pages are un-
-		 * pinned, and swapped out, they can end up swapped back
-		 * in above 4GB.  If pages are already in memory, then
-		 * shmem_read_mapping_page_gfp will ignore the gfpmask,
-		 * even if the already in-memory page disobeys the mask.
-		 *
-		 * It is only a theoretical issue today, because none of
-		 * the devices with this limitation can be populated with
-		 * enough memory to trigger the issue.  But this BUG_ON()
-		 * is here as a reminder in case the problem with
-		 * shmem_read_mapping_page_gfp() isn't solved by the time
-		 * it does become a real issue.
-		 *
-		 * See this thread: http://lkml.org/lkml/2011/7/11/238
-		 */
-		BUG_ON((gfpmask & __GFP_DMA32) &&
-				(page_to_pfn(p) >= 0x00100000UL));
-	}
-
-	return pages;
-
-fail:
-	while (i--)
-		page_cache_release(pages[i]);
-
-	drm_free_large(pages);
-	return ERR_CAST(p);
-}
-
-/**
- * drm_gem_put_pages - helper to free backing pages for a GEM object
- * @obj: obj in question
- * @pages: pages to free
- */
-void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
-		bool dirty, bool accessed)
-{
-	int i, npages;
-
-	npages = obj->size >> PAGE_SHIFT;
-
-	for (i = 0; i < npages; i++) {
-		if (dirty)
-			set_page_dirty(pages[i]);
-
-		if (accessed)
-			mark_page_accessed(pages[i]);
-
-		/* Undo the reference we took when populating the table */
-		page_cache_release(pages[i]);
-	}
-
-	drm_free_large(pages);
-}
-
-int
-_drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-
-	return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
-				  size / PAGE_SIZE);
-}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/9] drm: const'ify ioctls table (v2)
  2013-08-07 17:41 ` [PATCH 4/9] drm: const'ify ioctls table (v2) Rob Clark
@ 2013-08-07 17:48   ` Rob Clark
  0 siblings, 0 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 17:48 UTC (permalink / raw)
  To: dri-devel

oh, whoops, this one is already on drm-next

On Wed, Aug 7, 2013 at 1:41 PM, Rob Clark <robdclark@gmail.com> wrote:
> Because, there is no reason for it not to be const.
>
> v1: original
> v2: fix compile break in vmwgfx, and couple related cleanups suggested
>     by Ville Syrjälä
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_drv.c | 4 ++--
>  drivers/gpu/drm/gma500/psb_drv.c        | 2 +-
>  drivers/gpu/drm/i810/i810_dma.c         | 2 +-
>  drivers/gpu/drm/i810/i810_drv.h         | 2 +-
>  drivers/gpu/drm/i915/i915_dma.c         | 2 +-
>  drivers/gpu/drm/i915/i915_drv.h         | 2 +-
>  drivers/gpu/drm/mga/mga_drv.h           | 2 +-
>  drivers/gpu/drm/mga/mga_state.c         | 2 +-
>  drivers/gpu/drm/nouveau/nouveau_drm.c   | 5 ++---
>  drivers/gpu/drm/omapdrm/omap_drv.c      | 2 +-
>  drivers/gpu/drm/qxl/qxl_drv.h           | 2 +-
>  drivers/gpu/drm/qxl/qxl_ioctl.c         | 2 +-
>  drivers/gpu/drm/r128/r128_drv.h         | 2 +-
>  drivers/gpu/drm/r128/r128_state.c       | 2 +-
>  drivers/gpu/drm/radeon/radeon_drv.c     | 2 +-
>  drivers/gpu/drm/radeon/radeon_kms.c     | 2 +-
>  drivers/gpu/drm/savage/savage_bci.c     | 2 +-
>  drivers/gpu/drm/savage/savage_drv.h     | 2 +-
>  drivers/gpu/drm/sis/sis_drv.h           | 2 +-
>  drivers/gpu/drm/sis/sis_mm.c            | 2 +-
>  drivers/gpu/drm/via/via_dma.c           | 2 +-
>  drivers/gpu/drm/via/via_drv.h           | 2 +-
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c     | 4 ++--
>  drivers/gpu/host1x/drm/drm.c            | 2 +-
>  drivers/staging/imx-drm/imx-drm-core.c  | 2 +-
>  include/drm/drmP.h                      | 2 +-
>  26 files changed, 29 insertions(+), 30 deletions(-)
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/9] drm: add flip-work helper
  2013-08-07 17:41 ` [PATCH 1/9] drm: add flip-work helper Rob Clark
@ 2013-08-07 17:49   ` Daniel Vetter
  2013-08-07 18:20     ` Rob Clark
  0 siblings, 1 reply; 20+ messages in thread
From: Daniel Vetter @ 2013-08-07 17:49 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

On Wed, Aug 07, 2013 at 01:41:19PM -0400, Rob Clark wrote:
> A small helper to queue up work to do, from workqueue context, after a
> flip.  Typically useful to defer unreffing buffers that may be read by
> the display controller until vblank.
> 
> Signed-off-by: Rob Clark <robdclark@gmail.com>

Since you have this nice kerneldoc already here, can you please integrate
it all into the drm DocBook where all the other helpers are?

I don't think I'll use these for i915, but I can see that they're useful
for simple kms drivers. So

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

if the DocBook gets wired up.

Cheers, Daniel


> ---
>  drivers/gpu/drm/Makefile        |   2 +-
>  drivers/gpu/drm/drm_flip_work.c | 124 ++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_flip_work.h     |  71 +++++++++++++++++++++++
>  3 files changed, 196 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/drm_flip_work.c
>  create mode 100644 include/drm/drm_flip_work.h
> 
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index d943b94..2aaf082 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -13,7 +13,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
>  		drm_crtc.o drm_modes.o drm_edid.o \
>  		drm_info.o drm_debugfs.o drm_encoder_slave.o \
>  		drm_trace_points.o drm_global.o drm_prime.o \
> -		drm_rect.o drm_vma_manager.o
> +		drm_rect.o drm_vma_manager.o drm_flip_work.o
>  
>  drm-$(CONFIG_COMPAT) += drm_ioc32.o
>  drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
> diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c
> new file mode 100644
> index 0000000..e788882
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_flip_work.c
> @@ -0,0 +1,124 @@
> +/*
> + * Copyright (C) 2013 Red Hat
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include "drmP.h"
> +#include "drm_flip_work.h"
> +
> +/**
> + * drm_flip_work_queue - queue work
> + * @work: the flip-work
> + * @val: the value to queue
> + *
> + * Queues work, that will later be run (passed back to drm_flip_func_t
> + * func) on a work queue after drm_flip_work_commit() is called.
> + */
> +void drm_flip_work_queue(struct drm_flip_work *work, void *val)
> +{
> +	if (kfifo_put(&work->fifo, (const void **)&val)) {
> +		atomic_inc(&work->pending);
> +	} else {
> +		DRM_ERROR("%s fifo full!\n", work->name);
> +		work->func(work, val);
> +	}
> +}
> +EXPORT_SYMBOL(drm_flip_work_queue);
> +
> +/**
> + * drm_flip_work_commit - commit queued work
> + * @work: the flip-work
> + * @wq: the work-queue to run the queued work on
> + *
> + * Trigger work previously queued by drm_flip_work_queue() to run
> + * on a workqueue.  The typical usage would be to queue work (via
> + * drm_flip_work_queue()) at any point (from vblank irq and/or
> + * prior), and then from vblank irq commit the queued work.
> + */
> +void drm_flip_work_commit(struct drm_flip_work *work,
> +		struct workqueue_struct *wq)
> +{
> +	uint32_t pending = atomic_read(&work->pending);
> +	atomic_add(pending, &work->count);
> +	atomic_sub(pending, &work->pending);
> +	queue_work(wq, &work->worker);
> +}
> +EXPORT_SYMBOL(drm_flip_work_commit);
> +
> +static void flip_worker(struct work_struct *w)
> +{
> +	struct drm_flip_work *work = container_of(w, struct drm_flip_work, worker);
> +	uint32_t count = atomic_read(&work->count);
> +	void *val = NULL;
> +
> +	atomic_sub(count, &work->count);
> +
> +	while(count--)
> +		if (!WARN_ON(!kfifo_get(&work->fifo, &val)))
> +			work->func(work, val);
> +}
> +
> +/**
> + * drm_flip_work_init - initialize flip-work
> + * @work: the flip-work to initialize
> + * @size: the max queue depth
> + * @name: debug name
> + * @func: the callback work function
> + *
> + * Initializes/allocates resources for the flip-work
> + *
> + * RETURNS:
> + * Zero on success, error code on failure.
> + */
> +int drm_flip_work_init(struct drm_flip_work *work, int size,
> +		const char *name, drm_flip_func_t func)
> +{
> +	int ret;
> +
> +	work->name = name;
> +	atomic_set(&work->count, 0);
> +	atomic_set(&work->pending, 0);
> +	work->func = func;
> +
> +	ret = kfifo_alloc(&work->fifo, size, GFP_KERNEL);
> +	if (ret) {
> +		DRM_ERROR("could not allocate %s fifo\n", name);
> +		return ret;
> +	}
> +
> +	INIT_WORK(&work->worker, flip_worker);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_flip_work_init);
> +
> +/**
> + * drm_flip_work_cleanup - cleans up flip-work
> + * @work: the flip-work to cleanup
> + *
> + * Destroy resources allocated for the flip-work
> + */
> +void drm_flip_work_cleanup(struct drm_flip_work *work)
> +{
> +	WARN_ON(!kfifo_is_empty(&work->fifo));
> +	kfifo_free(&work->fifo);
> +}
> +EXPORT_SYMBOL(drm_flip_work_cleanup);
> diff --git a/include/drm/drm_flip_work.h b/include/drm/drm_flip_work.h
> new file mode 100644
> index 0000000..7d3840b
> --- /dev/null
> +++ b/include/drm/drm_flip_work.h
> @@ -0,0 +1,71 @@
> +/*
> + * Copyright (C) 2013 Red Hat
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef DRM_FLIP_WORK_H
> +#define DRM_FLIP_WORK_H
> +
> +#include <linux/kfifo.h>
> +#include <linux/workqueue.h>
> +
> +/**
> + * DOC: flip utils
> + *
> + * Util to queue up work to run from work-queue context after flip/vblank.
> + * Typically this can be used to defer unref of framebuffer's, cursor
> + * bo's, etc until after vblank.  The APIs are all safe (and lockless)
> + * for up to one producer and once consumer at a time.  The single-consumer
> + * aspect is ensured by committing the queued work to a single work-queue.
> + */
> +
> +struct drm_flip_work;
> +
> +/**
> + * drm_flip_func_t - callback function
> + *
> + * @work: the flip work
> + * @val: value queued via drm_flip_work_queue()
> + *
> + * Callback function to be called for each of the  queue'd work items after
> + * drm_flip_work_commit() is called.
> + */
> +typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);
> +
> +/**
> + * struct drm_flip_work - flip work queue
> + */
> +struct drm_flip_work {
> +	const char *name;
> +	atomic_t pending, count;
> +	drm_flip_func_t func;
> +	struct work_struct worker;
> +	DECLARE_KFIFO_PTR(fifo, void *);
> +};
> +
> +void drm_flip_work_queue(struct drm_flip_work *work, void *val);
> +void drm_flip_work_commit(struct drm_flip_work *work,
> +		struct workqueue_struct *wq);
> +int drm_flip_work_init(struct drm_flip_work *work, int size,
> +		const char *name, drm_flip_func_t func);
> +void drm_flip_work_cleanup(struct drm_flip_work *work);
> +
> +#endif  /* DRM_FLIP_WORK_H */
> -- 
> 1.8.3.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/9] drm: add flip-work helper
  2013-08-07 17:49   ` Daniel Vetter
@ 2013-08-07 18:20     ` Rob Clark
  2013-08-07 18:41       ` Rob Clark
  0 siblings, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-08-07 18:20 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: dri-devel

On Wed, Aug 7, 2013 at 1:49 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Wed, Aug 07, 2013 at 01:41:19PM -0400, Rob Clark wrote:
>> A small helper to queue up work to do, from workqueue context, after a
>> flip.  Typically useful to defer unreffing buffers that may be read by
>> the display controller until vblank.
>>
>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>
> Since you have this nice kerneldoc already here, can you please integrate
> it all into the drm DocBook where all the other helpers are?
>
> I don't think I'll use these for i915, but I can see that they're useful
> for simple kms drivers. So
>
> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> if the DocBook gets wired up.
>

something like:

-----------
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 87e22ec..3a8cdaf 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -2213,6 +2213,12 @@ void intel_crt_init(struct drm_device *dev)
 !Edrivers/gpu/drm/drm_rect.c
     </sect2>
     <sect2>
+      <title>Flip-work Helper Reference</title>
+!Pinclude/drm/drm_flip_work.h flip-work helper
+!Iinclude/drm/drm_flip_work.h
+!Edrivers/gpu/drm/drm_flip_work.c
+    </sect2>
+    <sect2>
       <title>VMA Offset Manager</title>
 !Pdrivers/gpu/drm/drm_vma_manager.c vma offset manager
 !Edrivers/gpu/drm/drm_vma_manager.c
-----------

> Cheers, Daniel
>
>
>> ---
>>  drivers/gpu/drm/Makefile        |   2 +-
>>  drivers/gpu/drm/drm_flip_work.c | 124 ++++++++++++++++++++++++++++++++++++++++
>>  include/drm/drm_flip_work.h     |  71 +++++++++++++++++++++++
>>  3 files changed, 196 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/gpu/drm/drm_flip_work.c
>>  create mode 100644 include/drm/drm_flip_work.h
>>
>> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
>> index d943b94..2aaf082 100644
>> --- a/drivers/gpu/drm/Makefile
>> +++ b/drivers/gpu/drm/Makefile
>> @@ -13,7 +13,7 @@ drm-y       :=      drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
>>               drm_crtc.o drm_modes.o drm_edid.o \
>>               drm_info.o drm_debugfs.o drm_encoder_slave.o \
>>               drm_trace_points.o drm_global.o drm_prime.o \
>> -             drm_rect.o drm_vma_manager.o
>> +             drm_rect.o drm_vma_manager.o drm_flip_work.o
>>
>>  drm-$(CONFIG_COMPAT) += drm_ioc32.o
>>  drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
>> diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c
>> new file mode 100644
>> index 0000000..e788882
>> --- /dev/null
>> +++ b/drivers/gpu/drm/drm_flip_work.c
>> @@ -0,0 +1,124 @@
>> +/*
>> + * Copyright (C) 2013 Red Hat
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including the next
>> + * paragraph) shall be included in all copies or substantial portions of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#include "drmP.h"
>> +#include "drm_flip_work.h"
>> +
>> +/**
>> + * drm_flip_work_queue - queue work
>> + * @work: the flip-work
>> + * @val: the value to queue
>> + *
>> + * Queues work, that will later be run (passed back to drm_flip_func_t
>> + * func) on a work queue after drm_flip_work_commit() is called.
>> + */
>> +void drm_flip_work_queue(struct drm_flip_work *work, void *val)
>> +{
>> +     if (kfifo_put(&work->fifo, (const void **)&val)) {
>> +             atomic_inc(&work->pending);
>> +     } else {
>> +             DRM_ERROR("%s fifo full!\n", work->name);
>> +             work->func(work, val);
>> +     }
>> +}
>> +EXPORT_SYMBOL(drm_flip_work_queue);
>> +
>> +/**
>> + * drm_flip_work_commit - commit queued work
>> + * @work: the flip-work
>> + * @wq: the work-queue to run the queued work on
>> + *
>> + * Trigger work previously queued by drm_flip_work_queue() to run
>> + * on a workqueue.  The typical usage would be to queue work (via
>> + * drm_flip_work_queue()) at any point (from vblank irq and/or
>> + * prior), and then from vblank irq commit the queued work.
>> + */
>> +void drm_flip_work_commit(struct drm_flip_work *work,
>> +             struct workqueue_struct *wq)
>> +{
>> +     uint32_t pending = atomic_read(&work->pending);
>> +     atomic_add(pending, &work->count);
>> +     atomic_sub(pending, &work->pending);
>> +     queue_work(wq, &work->worker);
>> +}
>> +EXPORT_SYMBOL(drm_flip_work_commit);
>> +
>> +static void flip_worker(struct work_struct *w)
>> +{
>> +     struct drm_flip_work *work = container_of(w, struct drm_flip_work, worker);
>> +     uint32_t count = atomic_read(&work->count);
>> +     void *val = NULL;
>> +
>> +     atomic_sub(count, &work->count);
>> +
>> +     while(count--)
>> +             if (!WARN_ON(!kfifo_get(&work->fifo, &val)))
>> +                     work->func(work, val);
>> +}
>> +
>> +/**
>> + * drm_flip_work_init - initialize flip-work
>> + * @work: the flip-work to initialize
>> + * @size: the max queue depth
>> + * @name: debug name
>> + * @func: the callback work function
>> + *
>> + * Initializes/allocates resources for the flip-work
>> + *
>> + * RETURNS:
>> + * Zero on success, error code on failure.
>> + */
>> +int drm_flip_work_init(struct drm_flip_work *work, int size,
>> +             const char *name, drm_flip_func_t func)
>> +{
>> +     int ret;
>> +
>> +     work->name = name;
>> +     atomic_set(&work->count, 0);
>> +     atomic_set(&work->pending, 0);
>> +     work->func = func;
>> +
>> +     ret = kfifo_alloc(&work->fifo, size, GFP_KERNEL);
>> +     if (ret) {
>> +             DRM_ERROR("could not allocate %s fifo\n", name);
>> +             return ret;
>> +     }
>> +
>> +     INIT_WORK(&work->worker, flip_worker);
>> +
>> +     return 0;
>> +}
>> +EXPORT_SYMBOL(drm_flip_work_init);
>> +
>> +/**
>> + * drm_flip_work_cleanup - cleans up flip-work
>> + * @work: the flip-work to cleanup
>> + *
>> + * Destroy resources allocated for the flip-work
>> + */
>> +void drm_flip_work_cleanup(struct drm_flip_work *work)
>> +{
>> +     WARN_ON(!kfifo_is_empty(&work->fifo));
>> +     kfifo_free(&work->fifo);
>> +}
>> +EXPORT_SYMBOL(drm_flip_work_cleanup);
>> diff --git a/include/drm/drm_flip_work.h b/include/drm/drm_flip_work.h
>> new file mode 100644
>> index 0000000..7d3840b
>> --- /dev/null
>> +++ b/include/drm/drm_flip_work.h
>> @@ -0,0 +1,71 @@
>> +/*
>> + * Copyright (C) 2013 Red Hat
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including the next
>> + * paragraph) shall be included in all copies or substantial portions of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + */
>> +
>> +#ifndef DRM_FLIP_WORK_H
>> +#define DRM_FLIP_WORK_H
>> +
>> +#include <linux/kfifo.h>
>> +#include <linux/workqueue.h>
>> +
>> +/**
>> + * DOC: flip utils
>> + *
>> + * Util to queue up work to run from work-queue context after flip/vblank.
>> + * Typically this can be used to defer unref of framebuffer's, cursor
>> + * bo's, etc until after vblank.  The APIs are all safe (and lockless)
>> + * for up to one producer and once consumer at a time.  The single-consumer
>> + * aspect is ensured by committing the queued work to a single work-queue.
>> + */
>> +
>> +struct drm_flip_work;
>> +
>> +/**
>> + * drm_flip_func_t - callback function
>> + *
>> + * @work: the flip work
>> + * @val: value queued via drm_flip_work_queue()
>> + *
>> + * Callback function to be called for each of the  queue'd work items after
>> + * drm_flip_work_commit() is called.
>> + */
>> +typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);
>> +
>> +/**
>> + * struct drm_flip_work - flip work queue
>> + */
>> +struct drm_flip_work {
>> +     const char *name;
>> +     atomic_t pending, count;
>> +     drm_flip_func_t func;
>> +     struct work_struct worker;
>> +     DECLARE_KFIFO_PTR(fifo, void *);
>> +};
>> +
>> +void drm_flip_work_queue(struct drm_flip_work *work, void *val);
>> +void drm_flip_work_commit(struct drm_flip_work *work,
>> +             struct workqueue_struct *wq);
>> +int drm_flip_work_init(struct drm_flip_work *work, int size,
>> +             const char *name, drm_flip_func_t func);
>> +void drm_flip_work_cleanup(struct drm_flip_work *work);
>> +
>> +#endif  /* DRM_FLIP_WORK_H */
>> --
>> 1.8.3.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 1/9] drm: add flip-work helper
  2013-08-07 18:20     ` Rob Clark
@ 2013-08-07 18:41       ` Rob Clark
  0 siblings, 0 replies; 20+ messages in thread
From: Rob Clark @ 2013-08-07 18:41 UTC (permalink / raw)
  To: dri-devel

A small helper to queue up work to do, from workqueue context, after a
flip.  Typically useful to defer unreffing buffers that may be read by
the display controller until vblank.

v1: original
v2: wire up docbook + couple docbook fixes

Signed-off-by: Rob Clark <robdclark@gmail.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 Documentation/DocBook/drm.tmpl  |   6 ++
 drivers/gpu/drm/Makefile        |   2 +-
 drivers/gpu/drm/drm_flip_work.c | 124 ++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_flip_work.h     |  76 ++++++++++++++++++++++++
 4 files changed, 207 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_flip_work.c
 create mode 100644 include/drm/drm_flip_work.h

diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 87e22ec..9b5862a 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -2213,6 +2213,12 @@ void intel_crt_init(struct drm_device *dev)
 !Edrivers/gpu/drm/drm_rect.c
     </sect2>
     <sect2>
+      <title>Flip-work Helper Reference</title>
+!Pinclude/drm/drm_flip_work.h flip utils
+!Iinclude/drm/drm_flip_work.h
+!Edrivers/gpu/drm/drm_flip_work.c
+    </sect2>
+    <sect2>
       <title>VMA Offset Manager</title>
 !Pdrivers/gpu/drm/drm_vma_manager.c vma offset manager
 !Edrivers/gpu/drm/drm_vma_manager.c
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index d943b94..2aaf082 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -13,7 +13,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
 		drm_trace_points.o drm_global.o drm_prime.o \
-		drm_rect.o drm_vma_manager.o
+		drm_rect.o drm_vma_manager.o drm_flip_work.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c
new file mode 100644
index 0000000..e788882
--- /dev/null
+++ b/drivers/gpu/drm/drm_flip_work.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_flip_work.h"
+
+/**
+ * drm_flip_work_queue - queue work
+ * @work: the flip-work
+ * @val: the value to queue
+ *
+ * Queues work, that will later be run (passed back to drm_flip_func_t
+ * func) on a work queue after drm_flip_work_commit() is called.
+ */
+void drm_flip_work_queue(struct drm_flip_work *work, void *val)
+{
+	if (kfifo_put(&work->fifo, (const void **)&val)) {
+		atomic_inc(&work->pending);
+	} else {
+		DRM_ERROR("%s fifo full!\n", work->name);
+		work->func(work, val);
+	}
+}
+EXPORT_SYMBOL(drm_flip_work_queue);
+
+/**
+ * drm_flip_work_commit - commit queued work
+ * @work: the flip-work
+ * @wq: the work-queue to run the queued work on
+ *
+ * Trigger work previously queued by drm_flip_work_queue() to run
+ * on a workqueue.  The typical usage would be to queue work (via
+ * drm_flip_work_queue()) at any point (from vblank irq and/or
+ * prior), and then from vblank irq commit the queued work.
+ */
+void drm_flip_work_commit(struct drm_flip_work *work,
+		struct workqueue_struct *wq)
+{
+	uint32_t pending = atomic_read(&work->pending);
+	atomic_add(pending, &work->count);
+	atomic_sub(pending, &work->pending);
+	queue_work(wq, &work->worker);
+}
+EXPORT_SYMBOL(drm_flip_work_commit);
+
+static void flip_worker(struct work_struct *w)
+{
+	struct drm_flip_work *work = container_of(w, struct drm_flip_work, worker);
+	uint32_t count = atomic_read(&work->count);
+	void *val = NULL;
+
+	atomic_sub(count, &work->count);
+
+	while(count--)
+		if (!WARN_ON(!kfifo_get(&work->fifo, &val)))
+			work->func(work, val);
+}
+
+/**
+ * drm_flip_work_init - initialize flip-work
+ * @work: the flip-work to initialize
+ * @size: the max queue depth
+ * @name: debug name
+ * @func: the callback work function
+ *
+ * Initializes/allocates resources for the flip-work
+ *
+ * RETURNS:
+ * Zero on success, error code on failure.
+ */
+int drm_flip_work_init(struct drm_flip_work *work, int size,
+		const char *name, drm_flip_func_t func)
+{
+	int ret;
+
+	work->name = name;
+	atomic_set(&work->count, 0);
+	atomic_set(&work->pending, 0);
+	work->func = func;
+
+	ret = kfifo_alloc(&work->fifo, size, GFP_KERNEL);
+	if (ret) {
+		DRM_ERROR("could not allocate %s fifo\n", name);
+		return ret;
+	}
+
+	INIT_WORK(&work->worker, flip_worker);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_flip_work_init);
+
+/**
+ * drm_flip_work_cleanup - cleans up flip-work
+ * @work: the flip-work to cleanup
+ *
+ * Destroy resources allocated for the flip-work
+ */
+void drm_flip_work_cleanup(struct drm_flip_work *work)
+{
+	WARN_ON(!kfifo_is_empty(&work->fifo));
+	kfifo_free(&work->fifo);
+}
+EXPORT_SYMBOL(drm_flip_work_cleanup);
diff --git a/include/drm/drm_flip_work.h b/include/drm/drm_flip_work.h
new file mode 100644
index 0000000..35c776a
--- /dev/null
+++ b/include/drm/drm_flip_work.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef DRM_FLIP_WORK_H
+#define DRM_FLIP_WORK_H
+
+#include <linux/kfifo.h>
+#include <linux/workqueue.h>
+
+/**
+ * DOC: flip utils
+ *
+ * Util to queue up work to run from work-queue context after flip/vblank.
+ * Typically this can be used to defer unref of framebuffer's, cursor
+ * bo's, etc until after vblank.  The APIs are all safe (and lockless)
+ * for up to one producer and once consumer at a time.  The single-consumer
+ * aspect is ensured by committing the queued work to a single work-queue.
+ */
+
+struct drm_flip_work;
+
+/*
+ * drm_flip_func_t - callback function
+ *
+ * @work: the flip work
+ * @val: value queued via drm_flip_work_queue()
+ *
+ * Callback function to be called for each of the  queue'd work items after
+ * drm_flip_work_commit() is called.
+ */
+typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);
+
+/**
+ * struct drm_flip_work - flip work queue
+ * @name: debug name
+ * @pending: number of queued but not committed items
+ * @count: number of committed items
+ * @func: callback fxn called for each committed item
+ * @worker: worker which calls @func
+ */
+struct drm_flip_work {
+	const char *name;
+	atomic_t pending, count;
+	drm_flip_func_t func;
+	struct work_struct worker;
+	DECLARE_KFIFO_PTR(fifo, void *);
+};
+
+void drm_flip_work_queue(struct drm_flip_work *work, void *val);
+void drm_flip_work_commit(struct drm_flip_work *work,
+		struct workqueue_struct *wq);
+int drm_flip_work_init(struct drm_flip_work *work, int size,
+		const char *name, drm_flip_func_t func);
+void drm_flip_work_cleanup(struct drm_flip_work *work);
+
+#endif  /* DRM_FLIP_WORK_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 9/9] drm/omap: kill omap_gem_helpers.c
  2013-08-07 17:41 ` [PATCH 9/9] drm/omap: kill omap_gem_helpers.c Rob Clark
@ 2013-08-07 20:13   ` Daniel Vetter
  0 siblings, 0 replies; 20+ messages in thread
From: Daniel Vetter @ 2013-08-07 20:13 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

On Wed, Aug 07, 2013 at 01:41:27PM -0400, Rob Clark wrote:
> Signed-off-by: Rob Clark <robdclark@gmail.com>

Patches 5-9 are Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/omapdrm/Makefile           |   3 -
>  drivers/gpu/drm/omapdrm/omap_gem.c         |   8 +-
>  drivers/gpu/drm/omapdrm/omap_gem_helpers.c | 124 -----------------------------
>  3 files changed, 4 insertions(+), 131 deletions(-)
>  delete mode 100644 drivers/gpu/drm/omapdrm/omap_gem_helpers.c
> 
> diff --git a/drivers/gpu/drm/omapdrm/Makefile b/drivers/gpu/drm/omapdrm/Makefile
> index d85e058..778372b 100644
> --- a/drivers/gpu/drm/omapdrm/Makefile
> +++ b/drivers/gpu/drm/omapdrm/Makefile
> @@ -18,7 +18,4 @@ omapdrm-y := omap_drv.o \
>  	omap_dmm_tiler.o \
>  	tcm-sita.o
>  
> -# temporary:
> -omapdrm-y += omap_gem_helpers.o
> -
>  obj-$(CONFIG_DRM_OMAP)	+= omapdrm.o
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
> index f90531fc00..030af5a 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem.c
> @@ -237,7 +237,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
>  	 * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
>  	 * we actually want CMA memory for it all anyways..
>  	 */
> -	pages = _drm_gem_get_pages(obj, GFP_KERNEL);
> +	pages = drm_gem_get_pages(obj, GFP_KERNEL);
>  	if (IS_ERR(pages)) {
>  		dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages));
>  		return PTR_ERR(pages);
> @@ -271,7 +271,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
>  	return 0;
>  
>  free_pages:
> -	_drm_gem_put_pages(obj, pages, true, false);
> +	drm_gem_put_pages(obj, pages, true, false);
>  
>  	return ret;
>  }
> @@ -295,7 +295,7 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)
>  	kfree(omap_obj->addrs);
>  	omap_obj->addrs = NULL;
>  
> -	_drm_gem_put_pages(obj, omap_obj->pages, true, false);
> +	drm_gem_put_pages(obj, omap_obj->pages, true, false);
>  	omap_obj->pages = NULL;
>  }
>  
> @@ -316,7 +316,7 @@ static uint64_t mmap_offset(struct drm_gem_object *obj)
>  
>  	/* Make it mmapable */
>  	size = omap_gem_mmap_size(obj);
> -	ret = _drm_gem_create_mmap_offset_size(obj, size);
> +	ret = drm_gem_create_mmap_offset_size(obj, size);
>  	if (ret) {
>  		dev_err(dev->dev, "could not allocate mmap offset\n");
>  		return 0;
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c b/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
> deleted file mode 100644
> index dbb1575..0000000
> --- a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
> +++ /dev/null
> @@ -1,124 +0,0 @@
> -/*
> - * drivers/gpu/drm/omapdrm/omap_gem_helpers.c
> - *
> - * Copyright (C) 2011 Texas Instruments
> - * Author: Rob Clark <rob.clark@linaro.org>
> - *
> - * This program is free software; you can redistribute it and/or modify it
> - * under the terms of the GNU General Public License version 2 as published by
> - * the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but WITHOUT
> - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> - * more details.
> - *
> - * You should have received a copy of the GNU General Public License along with
> - * this program.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -/* temporary copy of drm_gem_{get,put}_pages() until the
> - * "drm/gem: add functions to get/put pages" patch is merged..
> - */
> -
> -#include <linux/module.h>
> -#include <linux/types.h>
> -#include <linux/shmem_fs.h>
> -
> -#include <drm/drmP.h>
> -
> -/**
> - * drm_gem_get_pages - helper to allocate backing pages for a GEM object
> - * @obj: obj in question
> - * @gfpmask: gfp mask of requested pages
> - */
> -struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
> -{
> -	struct inode *inode;
> -	struct address_space *mapping;
> -	struct page *p, **pages;
> -	int i, npages;
> -
> -	/* This is the shared memory object that backs the GEM resource */
> -	inode = file_inode(obj->filp);
> -	mapping = inode->i_mapping;
> -
> -	npages = obj->size >> PAGE_SHIFT;
> -
> -	pages = drm_malloc_ab(npages, sizeof(struct page *));
> -	if (pages == NULL)
> -		return ERR_PTR(-ENOMEM);
> -
> -	gfpmask |= mapping_gfp_mask(mapping);
> -
> -	for (i = 0; i < npages; i++) {
> -		p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
> -		if (IS_ERR(p))
> -			goto fail;
> -		pages[i] = p;
> -
> -		/* There is a hypothetical issue w/ drivers that require
> -		 * buffer memory in the low 4GB.. if the pages are un-
> -		 * pinned, and swapped out, they can end up swapped back
> -		 * in above 4GB.  If pages are already in memory, then
> -		 * shmem_read_mapping_page_gfp will ignore the gfpmask,
> -		 * even if the already in-memory page disobeys the mask.
> -		 *
> -		 * It is only a theoretical issue today, because none of
> -		 * the devices with this limitation can be populated with
> -		 * enough memory to trigger the issue.  But this BUG_ON()
> -		 * is here as a reminder in case the problem with
> -		 * shmem_read_mapping_page_gfp() isn't solved by the time
> -		 * it does become a real issue.
> -		 *
> -		 * See this thread: http://lkml.org/lkml/2011/7/11/238
> -		 */
> -		BUG_ON((gfpmask & __GFP_DMA32) &&
> -				(page_to_pfn(p) >= 0x00100000UL));
> -	}
> -
> -	return pages;
> -
> -fail:
> -	while (i--)
> -		page_cache_release(pages[i]);
> -
> -	drm_free_large(pages);
> -	return ERR_CAST(p);
> -}
> -
> -/**
> - * drm_gem_put_pages - helper to free backing pages for a GEM object
> - * @obj: obj in question
> - * @pages: pages to free
> - */
> -void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
> -		bool dirty, bool accessed)
> -{
> -	int i, npages;
> -
> -	npages = obj->size >> PAGE_SHIFT;
> -
> -	for (i = 0; i < npages; i++) {
> -		if (dirty)
> -			set_page_dirty(pages[i]);
> -
> -		if (accessed)
> -			mark_page_accessed(pages[i]);
> -
> -		/* Undo the reference we took when populating the table */
> -		page_cache_release(pages[i]);
> -	}
> -
> -	drm_free_large(pages);
> -}
> -
> -int
> -_drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
> -{
> -	struct drm_device *dev = obj->dev;
> -	struct drm_gem_mm *mm = dev->mm_private;
> -
> -	return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
> -				  size / PAGE_SIZE);
> -}
> -- 
> 1.8.3.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 5/9] drm/gem: add drm_gem_create_mmap_offset_size()
  2013-08-07 17:41 ` [PATCH 5/9] drm/gem: add drm_gem_create_mmap_offset_size() Rob Clark
@ 2013-08-08 15:29   ` David Herrmann
  0 siblings, 0 replies; 20+ messages in thread
From: David Herrmann @ 2013-08-08 15:29 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

Hi

On Wed, Aug 7, 2013 at 7:41 PM, Rob Clark <robdclark@gmail.com> wrote:
> Variant of drm_gem_create_mmap_offset() which doesn't make the
> assumption that virtual size and physical size (obj->size) are the same.
> This is needed in omapdrm to deal with tiled buffers.  And lets us get
> rid of a duplicated and slightly modified version of
> drm_gem_create_mmap_offset() in omapdrm.
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>

Reviewed-by: David Herrmann <dh.herrmann@gmail.com>

Regards
David

> ---
>  drivers/gpu/drm/drm_gem.c | 28 ++++++++++++++++++++++++----
>  include/drm/drmP.h        |  1 +
>  2 files changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 1f76572..84d59f7 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -303,24 +303,44 @@ drm_gem_free_mmap_offset(struct drm_gem_object *obj)
>  EXPORT_SYMBOL(drm_gem_free_mmap_offset);
>
>  /**
> - * drm_gem_create_mmap_offset - create a fake mmap offset for an object
> + * drm_gem_create_mmap_offset_size - create a fake mmap offset for an object
>   * @obj: obj in question
> + * @size: the virtual size
>   *
>   * GEM memory mapping works by handing back to userspace a fake mmap offset
>   * it can use in a subsequent mmap(2) call.  The DRM core code then looks
>   * up the object based on the offset and sets up the various memory mapping
>   * structures.
>   *
> - * This routine allocates and attaches a fake offset for @obj.
> + * This routine allocates and attaches a fake offset for @obj, in cases where
> + * the virtual size differs from the physical size (ie. obj->size).  Otherwise
> + * just use drm_gem_create_mmap_offset().
>   */
>  int
> -drm_gem_create_mmap_offset(struct drm_gem_object *obj)
> +drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
>  {
>         struct drm_device *dev = obj->dev;
>         struct drm_gem_mm *mm = dev->mm_private;
>
>         return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
> -                                 obj->size / PAGE_SIZE);
> +                                 size / PAGE_SIZE);
> +}
> +EXPORT_SYMBOL(drm_gem_create_mmap_offset_size);
> +
> +/**
> + * drm_gem_create_mmap_offset - create a fake mmap offset for an object
> + * @obj: obj in question
> + *
> + * GEM memory mapping works by handing back to userspace a fake mmap offset
> + * it can use in a subsequent mmap(2) call.  The DRM core code then looks
> + * up the object based on the offset and sets up the various memory mapping
> + * structures.
> + *
> + * This routine allocates and attaches a fake offset for @obj.
> + */
> +int drm_gem_create_mmap_offset(struct drm_gem_object *obj)
> +{
> +       return drm_gem_create_mmap_offset_size(obj, obj->size);
>  }
>  EXPORT_SYMBOL(drm_gem_create_mmap_offset);
>
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 1cc765a..d00eb89 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1668,6 +1668,7 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
>
>  void drm_gem_free_mmap_offset(struct drm_gem_object *obj);
>  int drm_gem_create_mmap_offset(struct drm_gem_object *obj);
> +int drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
>
>  struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
>                                              struct drm_file *filp,
> --
> 1.8.3.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/9] drm/gma500: use gem get/put page helpers
  2013-08-07 17:41 ` [PATCH 7/9] drm/gma500: use gem " Rob Clark
@ 2013-10-08 19:57   ` Guillaume CLÉMENT
  2013-10-08 20:19     ` Rob Clark
  2013-10-08 20:31     ` Guillaume CLÉMENT
  0 siblings, 2 replies; 20+ messages in thread
From: Guillaume CLÉMENT @ 2013-10-08 19:57 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

On Wed, Aug 07, 2013 at 01:41:25PM -0400, Rob Clark wrote:
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
>  drivers/gpu/drm/gma500/gtt.c | 38 ++++++--------------------------------
>  1 file changed, 6 insertions(+), 32 deletions(-)
> [ snip ]

This is quite late to report, but I've just begun testing 3.12, and this
patch makes my screen garbled when using the modesetting xorg driver.

So far it looks like the buffer that the xorg driver gets is
not the one that is actually mapped by the kernel.

I'm currently trying to know what exactly causes the problem, but I don't
know anything about the internals here...


I doubt it will help, but the fbdev driver still works with this patch.


- Guillaume

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/9] drm/gma500: use gem get/put page helpers
  2013-10-08 19:57   ` Guillaume CLÉMENT
@ 2013-10-08 20:19     ` Rob Clark
  2013-10-08 20:22       ` Patrik Jakobsson
  2013-10-08 20:31     ` Guillaume CLÉMENT
  1 sibling, 1 reply; 20+ messages in thread
From: Rob Clark @ 2013-10-08 20:19 UTC (permalink / raw)
  To: Guillaume CLÉMENT; +Cc: dri-devel

On Tue, Oct 8, 2013 at 3:57 PM, Guillaume CLÉMENT <gclement@baobob.org> wrote:
> On Wed, Aug 07, 2013 at 01:41:25PM -0400, Rob Clark wrote:
>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>> ---
>>  drivers/gpu/drm/gma500/gtt.c | 38 ++++++--------------------------------
>>  1 file changed, 6 insertions(+), 32 deletions(-)
>> [ snip ]
>
> This is quite late to report, but I've just begun testing 3.12, and this
> patch makes my screen garbled when using the modesetting xorg driver.
>
> So far it looks like the buffer that the xorg driver gets is
> not the one that is actually mapped by the kernel.
>
> I'm currently trying to know what exactly causes the problem, but I don't
> know anything about the internals here...
>

could you try this small patch.. I think I missed something w/ my
original patch (sorry, no hw to test on here):

----------
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 92babac..2db731f 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -204,6 +204,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
     if (IS_ERR(pages))
         return PTR_ERR(pages);

+    gt->npage = gt->gem.size / PAGE_SIZE;
     gt->pages = pages;

     return 0;
----------


>
> I doubt it will help, but the fbdev driver still works with this patch.
>
>
> - Guillaume

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/9] drm/gma500: use gem get/put page helpers
  2013-10-08 20:19     ` Rob Clark
@ 2013-10-08 20:22       ` Patrik Jakobsson
  0 siblings, 0 replies; 20+ messages in thread
From: Patrik Jakobsson @ 2013-10-08 20:22 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

On Tue, Oct 8, 2013 at 10:19 PM, Rob Clark <robdclark@gmail.com> wrote:
> On Tue, Oct 8, 2013 at 3:57 PM, Guillaume CLÉMENT <gclement@baobob.org> wrote:
>> On Wed, Aug 07, 2013 at 01:41:25PM -0400, Rob Clark wrote:
>>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>>> ---
>>>  drivers/gpu/drm/gma500/gtt.c | 38 ++++++--------------------------------
>>>  1 file changed, 6 insertions(+), 32 deletions(-)
>>> [ snip ]
>>
>> This is quite late to report, but I've just begun testing 3.12, and this
>> patch makes my screen garbled when using the modesetting xorg driver.
>>
>> So far it looks like the buffer that the xorg driver gets is
>> not the one that is actually mapped by the kernel.
>>
>> I'm currently trying to know what exactly causes the problem, but I don't
>> know anything about the internals here...
>>
>
> could you try this small patch.. I think I missed something w/ my
> original patch (sorry, no hw to test on here):
>
> ----------
> diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
> index 92babac..2db731f 100644
> --- a/drivers/gpu/drm/gma500/gtt.c
> +++ b/drivers/gpu/drm/gma500/gtt.c
> @@ -204,6 +204,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
>      if (IS_ERR(pages))
>          return PTR_ERR(pages);
>
> +    gt->npage = gt->gem.size / PAGE_SIZE;
>      gt->pages = pages;
>
>      return 0;
> ----------
>

Rob, if this works, can you please make sure it goes into Dave's tree.
I'm currently travelling and I'll be away for at least one week.

Thanks
Patrik

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/9] drm/gma500: use gem get/put page helpers
  2013-10-08 19:57   ` Guillaume CLÉMENT
  2013-10-08 20:19     ` Rob Clark
@ 2013-10-08 20:31     ` Guillaume CLÉMENT
  1 sibling, 0 replies; 20+ messages in thread
From: Guillaume CLÉMENT @ 2013-10-08 20:31 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

> This is quite late to report, but I've just begun testing 3.12, and this
> patch makes my screen garbled when using the modesetting xorg driver.
>

Alright, after trying to notice what was different between the old and
new code, I've found the culprit :

-   gt->npage = pages;

There is no equivalent of this line with the new code. This must mess
things up.


By writing:

   gt->npage = gt->gem.size / PAGE_SIZE;

after:
   gt->npage = pages;

I don't experience the problem anymore. If this looks good to you, I'll
create a patch for this.



Thanks,

- Guillaume

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2013-10-08 20:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-07 17:41 [PATCH 0/9] deps for msm drm (flip-work helper, const ioctl table, and gem helpers) Rob Clark
2013-08-07 17:41 ` [PATCH 1/9] drm: add flip-work helper Rob Clark
2013-08-07 17:49   ` Daniel Vetter
2013-08-07 18:20     ` Rob Clark
2013-08-07 18:41       ` Rob Clark
2013-08-07 17:41 ` [PATCH 2/9] drm/tilcdc: use " Rob Clark
2013-08-07 17:41 ` [PATCH 3/9] drm/omap: " Rob Clark
2013-08-07 17:41 ` [PATCH 4/9] drm: const'ify ioctls table (v2) Rob Clark
2013-08-07 17:48   ` Rob Clark
2013-08-07 17:41 ` [PATCH 5/9] drm/gem: add drm_gem_create_mmap_offset_size() Rob Clark
2013-08-08 15:29   ` David Herrmann
2013-08-07 17:41 ` [PATCH 6/9] drm/gem: add shmem get/put page helpers Rob Clark
2013-08-07 17:41 ` [PATCH 7/9] drm/gma500: use gem " Rob Clark
2013-10-08 19:57   ` Guillaume CLÉMENT
2013-10-08 20:19     ` Rob Clark
2013-10-08 20:22       ` Patrik Jakobsson
2013-10-08 20:31     ` Guillaume CLÉMENT
2013-08-07 17:41 ` [PATCH 8/9] drm/udl: " Rob Clark
2013-08-07 17:41 ` [PATCH 9/9] drm/omap: kill omap_gem_helpers.c Rob Clark
2013-08-07 20:13   ` Daniel Vetter

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.