Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: add flip-work helper

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>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Rob Clark and committed by
Dave Airlie
cabaafc7 b17df86e

+207 -1
+6
Documentation/DocBook/drm.tmpl
··· 2213 2213 !Edrivers/gpu/drm/drm_rect.c 2214 2214 </sect2> 2215 2215 <sect2> 2216 + <title>Flip-work Helper Reference</title> 2217 + !Pinclude/drm/drm_flip_work.h flip utils 2218 + !Iinclude/drm/drm_flip_work.h 2219 + !Edrivers/gpu/drm/drm_flip_work.c 2220 + </sect2> 2221 + <sect2> 2216 2222 <title>VMA Offset Manager</title> 2217 2223 !Pdrivers/gpu/drm/drm_vma_manager.c vma offset manager 2218 2224 !Edrivers/gpu/drm/drm_vma_manager.c
+1 -1
drivers/gpu/drm/Makefile
··· 13 13 drm_crtc.o drm_modes.o drm_edid.o \ 14 14 drm_info.o drm_debugfs.o drm_encoder_slave.o \ 15 15 drm_trace_points.o drm_global.o drm_prime.o \ 16 - drm_rect.o drm_vma_manager.o 16 + drm_rect.o drm_vma_manager.o drm_flip_work.o 17 17 18 18 drm-$(CONFIG_COMPAT) += drm_ioc32.o 19 19 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+124
drivers/gpu/drm/drm_flip_work.c
··· 1 + /* 2 + * Copyright (C) 2013 Red Hat 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice (including the next 12 + * paragraph) shall be included in all copies or substantial portions of the 13 + * Software. 14 + * 15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 + * SOFTWARE. 22 + */ 23 + 24 + #include "drmP.h" 25 + #include "drm_flip_work.h" 26 + 27 + /** 28 + * drm_flip_work_queue - queue work 29 + * @work: the flip-work 30 + * @val: the value to queue 31 + * 32 + * Queues work, that will later be run (passed back to drm_flip_func_t 33 + * func) on a work queue after drm_flip_work_commit() is called. 34 + */ 35 + void drm_flip_work_queue(struct drm_flip_work *work, void *val) 36 + { 37 + if (kfifo_put(&work->fifo, (const void **)&val)) { 38 + atomic_inc(&work->pending); 39 + } else { 40 + DRM_ERROR("%s fifo full!\n", work->name); 41 + work->func(work, val); 42 + } 43 + } 44 + EXPORT_SYMBOL(drm_flip_work_queue); 45 + 46 + /** 47 + * drm_flip_work_commit - commit queued work 48 + * @work: the flip-work 49 + * @wq: the work-queue to run the queued work on 50 + * 51 + * Trigger work previously queued by drm_flip_work_queue() to run 52 + * on a workqueue. The typical usage would be to queue work (via 53 + * drm_flip_work_queue()) at any point (from vblank irq and/or 54 + * prior), and then from vblank irq commit the queued work. 55 + */ 56 + void drm_flip_work_commit(struct drm_flip_work *work, 57 + struct workqueue_struct *wq) 58 + { 59 + uint32_t pending = atomic_read(&work->pending); 60 + atomic_add(pending, &work->count); 61 + atomic_sub(pending, &work->pending); 62 + queue_work(wq, &work->worker); 63 + } 64 + EXPORT_SYMBOL(drm_flip_work_commit); 65 + 66 + static void flip_worker(struct work_struct *w) 67 + { 68 + struct drm_flip_work *work = container_of(w, struct drm_flip_work, worker); 69 + uint32_t count = atomic_read(&work->count); 70 + void *val = NULL; 71 + 72 + atomic_sub(count, &work->count); 73 + 74 + while(count--) 75 + if (!WARN_ON(!kfifo_get(&work->fifo, &val))) 76 + work->func(work, val); 77 + } 78 + 79 + /** 80 + * drm_flip_work_init - initialize flip-work 81 + * @work: the flip-work to initialize 82 + * @size: the max queue depth 83 + * @name: debug name 84 + * @func: the callback work function 85 + * 86 + * Initializes/allocates resources for the flip-work 87 + * 88 + * RETURNS: 89 + * Zero on success, error code on failure. 90 + */ 91 + int drm_flip_work_init(struct drm_flip_work *work, int size, 92 + const char *name, drm_flip_func_t func) 93 + { 94 + int ret; 95 + 96 + work->name = name; 97 + atomic_set(&work->count, 0); 98 + atomic_set(&work->pending, 0); 99 + work->func = func; 100 + 101 + ret = kfifo_alloc(&work->fifo, size, GFP_KERNEL); 102 + if (ret) { 103 + DRM_ERROR("could not allocate %s fifo\n", name); 104 + return ret; 105 + } 106 + 107 + INIT_WORK(&work->worker, flip_worker); 108 + 109 + return 0; 110 + } 111 + EXPORT_SYMBOL(drm_flip_work_init); 112 + 113 + /** 114 + * drm_flip_work_cleanup - cleans up flip-work 115 + * @work: the flip-work to cleanup 116 + * 117 + * Destroy resources allocated for the flip-work 118 + */ 119 + void drm_flip_work_cleanup(struct drm_flip_work *work) 120 + { 121 + WARN_ON(!kfifo_is_empty(&work->fifo)); 122 + kfifo_free(&work->fifo); 123 + } 124 + EXPORT_SYMBOL(drm_flip_work_cleanup);
+76
include/drm/drm_flip_work.h
··· 1 + /* 2 + * Copyright (C) 2013 Red Hat 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice (including the next 12 + * paragraph) shall be included in all copies or substantial portions of the 13 + * Software. 14 + * 15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 + * SOFTWARE. 22 + */ 23 + 24 + #ifndef DRM_FLIP_WORK_H 25 + #define DRM_FLIP_WORK_H 26 + 27 + #include <linux/kfifo.h> 28 + #include <linux/workqueue.h> 29 + 30 + /** 31 + * DOC: flip utils 32 + * 33 + * Util to queue up work to run from work-queue context after flip/vblank. 34 + * Typically this can be used to defer unref of framebuffer's, cursor 35 + * bo's, etc until after vblank. The APIs are all safe (and lockless) 36 + * for up to one producer and once consumer at a time. The single-consumer 37 + * aspect is ensured by committing the queued work to a single work-queue. 38 + */ 39 + 40 + struct drm_flip_work; 41 + 42 + /* 43 + * drm_flip_func_t - callback function 44 + * 45 + * @work: the flip work 46 + * @val: value queued via drm_flip_work_queue() 47 + * 48 + * Callback function to be called for each of the queue'd work items after 49 + * drm_flip_work_commit() is called. 50 + */ 51 + typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val); 52 + 53 + /** 54 + * struct drm_flip_work - flip work queue 55 + * @name: debug name 56 + * @pending: number of queued but not committed items 57 + * @count: number of committed items 58 + * @func: callback fxn called for each committed item 59 + * @worker: worker which calls @func 60 + */ 61 + struct drm_flip_work { 62 + const char *name; 63 + atomic_t pending, count; 64 + drm_flip_func_t func; 65 + struct work_struct worker; 66 + DECLARE_KFIFO_PTR(fifo, void *); 67 + }; 68 + 69 + void drm_flip_work_queue(struct drm_flip_work *work, void *val); 70 + void drm_flip_work_commit(struct drm_flip_work *work, 71 + struct workqueue_struct *wq); 72 + int drm_flip_work_init(struct drm_flip_work *work, int size, 73 + const char *name, drm_flip_func_t func); 74 + void drm_flip_work_cleanup(struct drm_flip_work *work); 75 + 76 + #endif /* DRM_FLIP_WORK_H */