1247835Skib/************************************************************************** 2247835Skib * 3247835Skib * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA 4247835Skib * All Rights Reserved. 5247835Skib * 6247835Skib * Permission is hereby granted, free of charge, to any person obtaining a 7247835Skib * copy of this software and associated documentation files (the 8247835Skib * "Software"), to deal in the Software without restriction, including 9247835Skib * without limitation the rights to use, copy, modify, merge, publish, 10247835Skib * distribute, sub license, and/or sell copies of the Software, and to 11247835Skib * permit persons to whom the Software is furnished to do so, subject to 12247835Skib * the following conditions: 13247835Skib * 14247835Skib * The above copyright notice and this permission notice (including the 15247835Skib * next paragraph) shall be included in all copies or substantial portions 16247835Skib * of the Software. 17247835Skib * 18247835Skib * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19247835Skib * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20247835Skib * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21247835Skib * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22247835Skib * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23247835Skib * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24247835Skib * USE OR OTHER DEALINGS IN THE SOFTWARE. 25247835Skib * 26247835Skib **************************************************************************/ 27247835Skib/* 28247835Skib * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> 29247835Skib */ 30247835Skib/* $FreeBSD$ */ 31247835Skib 32247835Skib/** @file ttm_lock.h 33247835Skib * This file implements a simple replacement for the buffer manager use 34247835Skib * of the DRM heavyweight hardware lock. 35247835Skib * The lock is a read-write lock. Taking it in read mode and write mode 36247835Skib * is relatively fast, and intended for in-kernel use only. 37247835Skib * 38247835Skib * The vt mode is used only when there is a need to block all 39247835Skib * user-space processes from validating buffers. 40247835Skib * It's allowed to leave kernel space with the vt lock held. 41247835Skib * If a user-space process dies while having the vt-lock, 42247835Skib * it will be released during the file descriptor release. The vt lock 43247835Skib * excludes write lock and read lock. 44247835Skib * 45247835Skib * The suspend mode is used to lock out all TTM users when preparing for 46247835Skib * and executing suspend operations. 47247835Skib * 48247835Skib */ 49247835Skib 50247835Skib#ifndef _TTM_LOCK_H_ 51247835Skib#define _TTM_LOCK_H_ 52247835Skib 53247835Skib#include <dev/drm2/drmP.h> 54247835Skib#include <dev/drm2/drm.h> 55247835Skib#include <dev/drm2/ttm/ttm_object.h> 56247835Skib 57247835Skib/** 58247835Skib * struct ttm_lock 59247835Skib * 60247835Skib * @base: ttm base object used solely to release the lock if the client 61247835Skib * holding the lock dies. 62247835Skib * @queue: Queue for processes waiting for lock change-of-status. 63247835Skib * @lock: Spinlock protecting some lock members. 64247835Skib * @rw: Read-write lock counter. Protected by @lock. 65247835Skib * @flags: Lock state. Protected by @lock. 66247835Skib * @kill_takers: Boolean whether to kill takers of the lock. 67247835Skib * @signal: Signal to send when kill_takers is true. 68247835Skib */ 69247835Skib 70247835Skibstruct ttm_lock { 71247835Skib struct ttm_base_object base; 72247835Skib struct mtx lock; 73247835Skib int32_t rw; 74247835Skib uint32_t flags; 75247835Skib bool kill_takers; 76247835Skib int signal; 77247835Skib struct ttm_object_file *vt_holder; 78247835Skib}; 79247835Skib 80247835Skib 81247835Skib/** 82247835Skib * ttm_lock_init 83247835Skib * 84247835Skib * @lock: Pointer to a struct ttm_lock 85247835Skib * Initializes the lock. 86247835Skib */ 87247835Skibextern void ttm_lock_init(struct ttm_lock *lock); 88247835Skib 89247835Skib/** 90247835Skib * ttm_read_unlock 91247835Skib * 92247835Skib * @lock: Pointer to a struct ttm_lock 93247835Skib * 94247835Skib * Releases a read lock. 95247835Skib */ 96247835Skibextern void ttm_read_unlock(struct ttm_lock *lock); 97247835Skib 98247835Skib/** 99247835Skib * ttm_read_lock 100247835Skib * 101247835Skib * @lock: Pointer to a struct ttm_lock 102247835Skib * @interruptible: Interruptible sleeping while waiting for a lock. 103247835Skib * 104247835Skib * Takes the lock in read mode. 105247835Skib * Returns: 106247835Skib * -ERESTARTSYS If interrupted by a signal and interruptible is true. 107247835Skib */ 108247835Skibextern int ttm_read_lock(struct ttm_lock *lock, bool interruptible); 109247835Skib 110247835Skib/** 111247835Skib * ttm_read_trylock 112247835Skib * 113247835Skib * @lock: Pointer to a struct ttm_lock 114247835Skib * @interruptible: Interruptible sleeping while waiting for a lock. 115247835Skib * 116247835Skib * Tries to take the lock in read mode. If the lock is already held 117247835Skib * in write mode, the function will return -EBUSY. If the lock is held 118247835Skib * in vt or suspend mode, the function will sleep until these modes 119247835Skib * are unlocked. 120247835Skib * 121247835Skib * Returns: 122247835Skib * -EBUSY The lock was already held in write mode. 123247835Skib * -ERESTARTSYS If interrupted by a signal and interruptible is true. 124247835Skib */ 125247835Skibextern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible); 126247835Skib 127247835Skib/** 128247835Skib * ttm_lock_downgrade 129247835Skib * 130247835Skib * @lock: Pointer to a struct ttm_lock 131247835Skib * 132247835Skib * Downgrades a write lock to a read lock. 133247835Skib */ 134247835Skibextern void ttm_lock_downgrade(struct ttm_lock *lock); 135247835Skib 136247835Skib/** 137247835Skib * ttm_suspend_lock 138247835Skib * 139247835Skib * @lock: Pointer to a struct ttm_lock 140247835Skib * 141247835Skib * Takes the lock in suspend mode. Excludes read and write mode. 142247835Skib */ 143247835Skibextern void ttm_suspend_lock(struct ttm_lock *lock); 144247835Skib 145247835Skib/** 146247835Skib * ttm_suspend_unlock 147247835Skib * 148247835Skib * @lock: Pointer to a struct ttm_lock 149247835Skib * 150247835Skib * Releases a suspend lock 151247835Skib */ 152247835Skibextern void ttm_suspend_unlock(struct ttm_lock *lock); 153247835Skib 154247835Skib/** 155247835Skib * ttm_vt_lock 156247835Skib * 157247835Skib * @lock: Pointer to a struct ttm_lock 158247835Skib * @interruptible: Interruptible sleeping while waiting for a lock. 159247835Skib * @tfile: Pointer to a struct ttm_object_file to register the lock with. 160247835Skib * 161247835Skib * Takes the lock in vt mode. 162247835Skib * Returns: 163247835Skib * -ERESTARTSYS If interrupted by a signal and interruptible is true. 164247835Skib * -ENOMEM: Out of memory when locking. 165247835Skib */ 166247835Skibextern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible, 167247835Skib struct ttm_object_file *tfile); 168247835Skib 169247835Skib/** 170247835Skib * ttm_vt_unlock 171247835Skib * 172247835Skib * @lock: Pointer to a struct ttm_lock 173247835Skib * 174247835Skib * Releases a vt lock. 175247835Skib * Returns: 176247835Skib * -EINVAL If the lock was not held. 177247835Skib */ 178247835Skibextern int ttm_vt_unlock(struct ttm_lock *lock); 179247835Skib 180247835Skib/** 181247835Skib * ttm_write_unlock 182247835Skib * 183247835Skib * @lock: Pointer to a struct ttm_lock 184247835Skib * 185247835Skib * Releases a write lock. 186247835Skib */ 187247835Skibextern void ttm_write_unlock(struct ttm_lock *lock); 188247835Skib 189247835Skib/** 190247835Skib * ttm_write_lock 191247835Skib * 192247835Skib * @lock: Pointer to a struct ttm_lock 193247835Skib * @interruptible: Interruptible sleeping while waiting for a lock. 194247835Skib * 195247835Skib * Takes the lock in write mode. 196247835Skib * Returns: 197247835Skib * -ERESTARTSYS If interrupted by a signal and interruptible is true. 198247835Skib */ 199247835Skibextern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); 200247835Skib 201247835Skibvoid ttm_write_lock_downgrade(struct ttm_lock *lock); 202247835Skib 203247835Skib/** 204247835Skib * ttm_lock_set_kill 205247835Skib * 206247835Skib * @lock: Pointer to a struct ttm_lock 207247835Skib * @val: Boolean whether to kill processes taking the lock. 208247835Skib * @signal: Signal to send to the process taking the lock. 209247835Skib * 210247835Skib * The kill-when-taking-lock functionality is used to kill processes that keep 211247835Skib * on using the TTM functionality when its resources has been taken down, for 212247835Skib * example when the X server exits. A typical sequence would look like this: 213247835Skib * - X server takes lock in write mode. 214247835Skib * - ttm_lock_set_kill() is called with @val set to true. 215247835Skib * - As part of X server exit, TTM resources are taken down. 216247835Skib * - X server releases the lock on file release. 217247835Skib * - Another dri client wants to render, takes the lock and is killed. 218247835Skib * 219247835Skib */ 220247835Skibstatic inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val, 221247835Skib int signal) 222247835Skib{ 223247835Skib lock->kill_takers = val; 224247835Skib if (val) 225247835Skib lock->signal = signal; 226247835Skib} 227247835Skib 228247835Skib#endif 229