aboutsummaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2014-11-14 13:30:29 -0500
committerDave Airlie <airlied@redhat.com>2014-11-14 18:25:35 -0500
commit8bd4ae202813ac04f35dacf43263e1cf96743292 (patch)
tree3271272039fa98b8482120dd559f197b00cdf774 /include/drm
parent7fd36c0bae07d8c7fa9668ea6ba28dbcb4f9955b (diff)
drm: rework flip-work helpers to avoid calling func when the FIFO is full
Make use of lists instead of kfifo in order to dynamically allocate task entry when someone require some delayed work, and thus preventing drm_flip_work_queue from directly calling func instead of queuing this call. This allow drm_flip_work_queue to be safely called even within irq handlers. Add new helper functions to allocate a flip work task and queue it when needed. This prevents allocating data within irq context (which might impact the time spent in the irq handler). Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com> Reviewed-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include/drm')
-rw-r--r--include/drm/drm_flip_work.h31
1 files changed, 23 insertions, 8 deletions
diff --git a/include/drm/drm_flip_work.h b/include/drm/drm_flip_work.h
index 9eed34dcd6af..3fcb4c44c9e0 100644
--- a/include/drm/drm_flip_work.h
+++ b/include/drm/drm_flip_work.h
@@ -25,6 +25,7 @@
25#define DRM_FLIP_WORK_H 25#define DRM_FLIP_WORK_H
26 26
27#include <linux/kfifo.h> 27#include <linux/kfifo.h>
28#include <linux/spinlock.h>
28#include <linux/workqueue.h> 29#include <linux/workqueue.h>
29 30
30/** 31/**
@@ -32,9 +33,9 @@
32 * 33 *
33 * Util to queue up work to run from work-queue context after flip/vblank. 34 * 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 * 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 * bo's, etc until after vblank. The APIs are all thread-safe.
36 * for up to one producer and once consumer at a time. The single-consumer 37 * Moreover, drm_flip_work_queue_task and drm_flip_work_queue can be called
37 * aspect is ensured by committing the queued work to a single work-queue. 38 * in atomic context.
38 */ 39 */
39 40
40struct drm_flip_work; 41struct drm_flip_work;
@@ -51,22 +52,36 @@ struct drm_flip_work;
51typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val); 52typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);
52 53
53/** 54/**
55 * struct drm_flip_task - flip work task
56 * @node: list entry element
57 * @data: data to pass to work->func
58 */
59struct drm_flip_task {
60 struct list_head node;
61 void *data;
62};
63
64/**
54 * struct drm_flip_work - flip work queue 65 * struct drm_flip_work - flip work queue
55 * @name: debug name 66 * @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 67 * @func: callback fxn called for each committed item
59 * @worker: worker which calls @func 68 * @worker: worker which calls @func
60 * @fifo: queue of committed items 69 * @queued: queued tasks
70 * @commited: commited tasks
71 * @lock: lock to access queued and commited lists
61 */ 72 */
62struct drm_flip_work { 73struct drm_flip_work {
63 const char *name; 74 const char *name;
64 atomic_t pending, count;
65 drm_flip_func_t func; 75 drm_flip_func_t func;
66 struct work_struct worker; 76 struct work_struct worker;
67 DECLARE_KFIFO_PTR(fifo, void *); 77 struct list_head queued;
78 struct list_head commited;
79 spinlock_t lock;
68}; 80};
69 81
82struct drm_flip_task *drm_flip_work_allocate_task(void *data, gfp_t flags);
83void drm_flip_work_queue_task(struct drm_flip_work *work,
84 struct drm_flip_task *task);
70void drm_flip_work_queue(struct drm_flip_work *work, void *val); 85void drm_flip_work_queue(struct drm_flip_work *work, void *val);
71void drm_flip_work_commit(struct drm_flip_work *work, 86void drm_flip_work_commit(struct drm_flip_work *work,
72 struct workqueue_struct *wq); 87 struct workqueue_struct *wq);