diff mbox

[1/9] drm: add flip-work helper

Message ID CAF6AEGsrMwgUXdDmRf2C=eRp4Xh2Q41_6SB5YU7RXr70wXm4Ow@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rob Clark Aug. 7, 2013, 6:20 p.m. UTC
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:

-----------
-----------

> 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
diff mbox

Patch

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