root/drivers/gpu/drm/drm_flip_work.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. drm_flip_work_allocate_task
  2. drm_flip_work_queue_task
  3. drm_flip_work_queue
  4. drm_flip_work_commit
  5. flip_worker
  6. drm_flip_work_init
  7. drm_flip_work_cleanup

   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 <linux/slab.h>
  25 
  26 #include <drm/drm_flip_work.h>
  27 #include <drm/drm_print.h>
  28 #include <drm/drm_util.h>
  29 
  30 /**
  31  * drm_flip_work_allocate_task - allocate a flip-work task
  32  * @data: data associated to the task
  33  * @flags: allocator flags
  34  *
  35  * Allocate a drm_flip_task object and attach private data to it.
  36  */
  37 struct drm_flip_task *drm_flip_work_allocate_task(void *data, gfp_t flags)
  38 {
  39         struct drm_flip_task *task;
  40 
  41         task = kzalloc(sizeof(*task), flags);
  42         if (task)
  43                 task->data = data;
  44 
  45         return task;
  46 }
  47 EXPORT_SYMBOL(drm_flip_work_allocate_task);
  48 
  49 /**
  50  * drm_flip_work_queue_task - queue a specific task
  51  * @work: the flip-work
  52  * @task: the task to handle
  53  *
  54  * Queues task, that will later be run (passed back to drm_flip_func_t
  55  * func) on a work queue after drm_flip_work_commit() is called.
  56  */
  57 void drm_flip_work_queue_task(struct drm_flip_work *work,
  58                               struct drm_flip_task *task)
  59 {
  60         unsigned long flags;
  61 
  62         spin_lock_irqsave(&work->lock, flags);
  63         list_add_tail(&task->node, &work->queued);
  64         spin_unlock_irqrestore(&work->lock, flags);
  65 }
  66 EXPORT_SYMBOL(drm_flip_work_queue_task);
  67 
  68 /**
  69  * drm_flip_work_queue - queue work
  70  * @work: the flip-work
  71  * @val: the value to queue
  72  *
  73  * Queues work, that will later be run (passed back to drm_flip_func_t
  74  * func) on a work queue after drm_flip_work_commit() is called.
  75  */
  76 void drm_flip_work_queue(struct drm_flip_work *work, void *val)
  77 {
  78         struct drm_flip_task *task;
  79 
  80         task = drm_flip_work_allocate_task(val,
  81                                 drm_can_sleep() ? GFP_KERNEL : GFP_ATOMIC);
  82         if (task) {
  83                 drm_flip_work_queue_task(work, task);
  84         } else {
  85                 DRM_ERROR("%s could not allocate task!\n", work->name);
  86                 work->func(work, val);
  87         }
  88 }
  89 EXPORT_SYMBOL(drm_flip_work_queue);
  90 
  91 /**
  92  * drm_flip_work_commit - commit queued work
  93  * @work: the flip-work
  94  * @wq: the work-queue to run the queued work on
  95  *
  96  * Trigger work previously queued by drm_flip_work_queue() to run
  97  * on a workqueue.  The typical usage would be to queue work (via
  98  * drm_flip_work_queue()) at any point (from vblank irq and/or
  99  * prior), and then from vblank irq commit the queued work.
 100  */
 101 void drm_flip_work_commit(struct drm_flip_work *work,
 102                 struct workqueue_struct *wq)
 103 {
 104         unsigned long flags;
 105 
 106         spin_lock_irqsave(&work->lock, flags);
 107         list_splice_tail(&work->queued, &work->commited);
 108         INIT_LIST_HEAD(&work->queued);
 109         spin_unlock_irqrestore(&work->lock, flags);
 110         queue_work(wq, &work->worker);
 111 }
 112 EXPORT_SYMBOL(drm_flip_work_commit);
 113 
 114 static void flip_worker(struct work_struct *w)
 115 {
 116         struct drm_flip_work *work = container_of(w, struct drm_flip_work, worker);
 117         struct list_head tasks;
 118         unsigned long flags;
 119 
 120         while (1) {
 121                 struct drm_flip_task *task, *tmp;
 122 
 123                 INIT_LIST_HEAD(&tasks);
 124                 spin_lock_irqsave(&work->lock, flags);
 125                 list_splice_tail(&work->commited, &tasks);
 126                 INIT_LIST_HEAD(&work->commited);
 127                 spin_unlock_irqrestore(&work->lock, flags);
 128 
 129                 if (list_empty(&tasks))
 130                         break;
 131 
 132                 list_for_each_entry_safe(task, tmp, &tasks, node) {
 133                         work->func(work, task->data);
 134                         kfree(task);
 135                 }
 136         }
 137 }
 138 
 139 /**
 140  * drm_flip_work_init - initialize flip-work
 141  * @work: the flip-work to initialize
 142  * @name: debug name
 143  * @func: the callback work function
 144  *
 145  * Initializes/allocates resources for the flip-work
 146  */
 147 void drm_flip_work_init(struct drm_flip_work *work,
 148                 const char *name, drm_flip_func_t func)
 149 {
 150         work->name = name;
 151         INIT_LIST_HEAD(&work->queued);
 152         INIT_LIST_HEAD(&work->commited);
 153         spin_lock_init(&work->lock);
 154         work->func = func;
 155 
 156         INIT_WORK(&work->worker, flip_worker);
 157 }
 158 EXPORT_SYMBOL(drm_flip_work_init);
 159 
 160 /**
 161  * drm_flip_work_cleanup - cleans up flip-work
 162  * @work: the flip-work to cleanup
 163  *
 164  * Destroy resources allocated for the flip-work
 165  */
 166 void drm_flip_work_cleanup(struct drm_flip_work *work)
 167 {
 168         WARN_ON(!list_empty(&work->queued) || !list_empty(&work->commited));
 169 }
 170 EXPORT_SYMBOL(drm_flip_work_cleanup);

/* [<][>][^][v][top][bottom][index][help] */