root/drivers/gpu/drm/vmwgfx/ttm_lock.c

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

DEFINITIONS

This source file includes following definitions.
  1. ttm_lock_init
  2. ttm_read_unlock
  3. __ttm_read_lock
  4. ttm_read_lock
  5. __ttm_read_trylock
  6. ttm_read_trylock
  7. ttm_write_unlock
  8. __ttm_write_lock
  9. ttm_write_lock
  10. ttm_suspend_unlock
  11. __ttm_suspend_lock
  12. ttm_suspend_lock

   1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
   2 /**************************************************************************
   3  *
   4  * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA
   5  * All Rights Reserved.
   6  *
   7  * Permission is hereby granted, free of charge, to any person obtaining a
   8  * copy of this software and associated documentation files (the
   9  * "Software"), to deal in the Software without restriction, including
  10  * without limitation the rights to use, copy, modify, merge, publish,
  11  * distribute, sub license, and/or sell copies of the Software, and to
  12  * permit persons to whom the Software is furnished to do so, subject to
  13  * the following conditions:
  14  *
  15  * The above copyright notice and this permission notice (including the
  16  * next paragraph) shall be included in all copies or substantial portions
  17  * of the Software.
  18  *
  19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  22  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  23  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  25  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  26  *
  27  **************************************************************************/
  28 /*
  29  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  30  */
  31 
  32 #include <linux/atomic.h>
  33 #include <linux/errno.h>
  34 #include <linux/wait.h>
  35 #include <linux/sched/signal.h>
  36 #include "ttm_lock.h"
  37 #include "ttm_object.h"
  38 
  39 #define TTM_WRITE_LOCK_PENDING    (1 << 0)
  40 #define TTM_VT_LOCK_PENDING       (1 << 1)
  41 #define TTM_SUSPEND_LOCK_PENDING  (1 << 2)
  42 #define TTM_VT_LOCK               (1 << 3)
  43 #define TTM_SUSPEND_LOCK          (1 << 4)
  44 
  45 void ttm_lock_init(struct ttm_lock *lock)
  46 {
  47         spin_lock_init(&lock->lock);
  48         init_waitqueue_head(&lock->queue);
  49         lock->rw = 0;
  50         lock->flags = 0;
  51 }
  52 
  53 void ttm_read_unlock(struct ttm_lock *lock)
  54 {
  55         spin_lock(&lock->lock);
  56         if (--lock->rw == 0)
  57                 wake_up_all(&lock->queue);
  58         spin_unlock(&lock->lock);
  59 }
  60 
  61 static bool __ttm_read_lock(struct ttm_lock *lock)
  62 {
  63         bool locked = false;
  64 
  65         spin_lock(&lock->lock);
  66         if (lock->rw >= 0 && lock->flags == 0) {
  67                 ++lock->rw;
  68                 locked = true;
  69         }
  70         spin_unlock(&lock->lock);
  71         return locked;
  72 }
  73 
  74 int ttm_read_lock(struct ttm_lock *lock, bool interruptible)
  75 {
  76         int ret = 0;
  77 
  78         if (interruptible)
  79                 ret = wait_event_interruptible(lock->queue,
  80                                                __ttm_read_lock(lock));
  81         else
  82                 wait_event(lock->queue, __ttm_read_lock(lock));
  83         return ret;
  84 }
  85 
  86 static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked)
  87 {
  88         bool block = true;
  89 
  90         *locked = false;
  91 
  92         spin_lock(&lock->lock);
  93         if (lock->rw >= 0 && lock->flags == 0) {
  94                 ++lock->rw;
  95                 block = false;
  96                 *locked = true;
  97         } else if (lock->flags == 0) {
  98                 block = false;
  99         }
 100         spin_unlock(&lock->lock);
 101 
 102         return !block;
 103 }
 104 
 105 int ttm_read_trylock(struct ttm_lock *lock, bool interruptible)
 106 {
 107         int ret = 0;
 108         bool locked;
 109 
 110         if (interruptible)
 111                 ret = wait_event_interruptible
 112                         (lock->queue, __ttm_read_trylock(lock, &locked));
 113         else
 114                 wait_event(lock->queue, __ttm_read_trylock(lock, &locked));
 115 
 116         if (unlikely(ret != 0)) {
 117                 BUG_ON(locked);
 118                 return ret;
 119         }
 120 
 121         return (locked) ? 0 : -EBUSY;
 122 }
 123 
 124 void ttm_write_unlock(struct ttm_lock *lock)
 125 {
 126         spin_lock(&lock->lock);
 127         lock->rw = 0;
 128         wake_up_all(&lock->queue);
 129         spin_unlock(&lock->lock);
 130 }
 131 
 132 static bool __ttm_write_lock(struct ttm_lock *lock)
 133 {
 134         bool locked = false;
 135 
 136         spin_lock(&lock->lock);
 137         if (lock->rw == 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDING) == 0)) {
 138                 lock->rw = -1;
 139                 lock->flags &= ~TTM_WRITE_LOCK_PENDING;
 140                 locked = true;
 141         } else {
 142                 lock->flags |= TTM_WRITE_LOCK_PENDING;
 143         }
 144         spin_unlock(&lock->lock);
 145         return locked;
 146 }
 147 
 148 int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
 149 {
 150         int ret = 0;
 151 
 152         if (interruptible) {
 153                 ret = wait_event_interruptible(lock->queue,
 154                                                __ttm_write_lock(lock));
 155                 if (unlikely(ret != 0)) {
 156                         spin_lock(&lock->lock);
 157                         lock->flags &= ~TTM_WRITE_LOCK_PENDING;
 158                         wake_up_all(&lock->queue);
 159                         spin_unlock(&lock->lock);
 160                 }
 161         } else
 162                 wait_event(lock->queue, __ttm_write_lock(lock));
 163 
 164         return ret;
 165 }
 166 
 167 void ttm_suspend_unlock(struct ttm_lock *lock)
 168 {
 169         spin_lock(&lock->lock);
 170         lock->flags &= ~TTM_SUSPEND_LOCK;
 171         wake_up_all(&lock->queue);
 172         spin_unlock(&lock->lock);
 173 }
 174 
 175 static bool __ttm_suspend_lock(struct ttm_lock *lock)
 176 {
 177         bool locked = false;
 178 
 179         spin_lock(&lock->lock);
 180         if (lock->rw == 0) {
 181                 lock->flags &= ~TTM_SUSPEND_LOCK_PENDING;
 182                 lock->flags |= TTM_SUSPEND_LOCK;
 183                 locked = true;
 184         } else {
 185                 lock->flags |= TTM_SUSPEND_LOCK_PENDING;
 186         }
 187         spin_unlock(&lock->lock);
 188         return locked;
 189 }
 190 
 191 void ttm_suspend_lock(struct ttm_lock *lock)
 192 {
 193         wait_event(lock->queue, __ttm_suspend_lock(lock));
 194 }

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