/**************************************************************************1*2* Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL20* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,21* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR22* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE23* USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/26/*27* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>28*/2930/** @file ttm_lock.h31* This file implements a simple replacement for the buffer manager use32* of the DRM heavyweight hardware lock.33* The lock is a read-write lock. Taking it in read mode and write mode34* is relatively fast, and intended for in-kernel use only.35*36* The vt mode is used only when there is a need to block all37* user-space processes from validating buffers.38* It's allowed to leave kernel space with the vt lock held.39* If a user-space process dies while having the vt-lock,40* it will be released during the file descriptor release. The vt lock41* excludes write lock and read lock.42*43* The suspend mode is used to lock out all TTM users when preparing for44* and executing suspend operations.45*46*/4748#ifndef _TTM_LOCK_H_49#define _TTM_LOCK_H_5051#include "ttm/ttm_object.h"52#include <linux/wait.h>53#include <asm/atomic.h>5455/**56* struct ttm_lock57*58* @base: ttm base object used solely to release the lock if the client59* holding the lock dies.60* @queue: Queue for processes waiting for lock change-of-status.61* @lock: Spinlock protecting some lock members.62* @rw: Read-write lock counter. Protected by @lock.63* @flags: Lock state. Protected by @lock.64* @kill_takers: Boolean whether to kill takers of the lock.65* @signal: Signal to send when kill_takers is true.66*/6768struct ttm_lock {69struct ttm_base_object base;70wait_queue_head_t queue;71spinlock_t lock;72int32_t rw;73uint32_t flags;74bool kill_takers;75int signal;76struct ttm_object_file *vt_holder;77};787980/**81* ttm_lock_init82*83* @lock: Pointer to a struct ttm_lock84* Initializes the lock.85*/86extern void ttm_lock_init(struct ttm_lock *lock);8788/**89* ttm_read_unlock90*91* @lock: Pointer to a struct ttm_lock92*93* Releases a read lock.94*/95extern void ttm_read_unlock(struct ttm_lock *lock);9697/**98* ttm_read_lock99*100* @lock: Pointer to a struct ttm_lock101* @interruptible: Interruptible sleeping while waiting for a lock.102*103* Takes the lock in read mode.104* Returns:105* -ERESTARTSYS If interrupted by a signal and interruptible is true.106*/107extern int ttm_read_lock(struct ttm_lock *lock, bool interruptible);108109/**110* ttm_read_trylock111*112* @lock: Pointer to a struct ttm_lock113* @interruptible: Interruptible sleeping while waiting for a lock.114*115* Tries to take the lock in read mode. If the lock is already held116* in write mode, the function will return -EBUSY. If the lock is held117* in vt or suspend mode, the function will sleep until these modes118* are unlocked.119*120* Returns:121* -EBUSY The lock was already held in write mode.122* -ERESTARTSYS If interrupted by a signal and interruptible is true.123*/124extern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible);125126/**127* ttm_write_unlock128*129* @lock: Pointer to a struct ttm_lock130*131* Releases a write lock.132*/133extern void ttm_write_unlock(struct ttm_lock *lock);134135/**136* ttm_write_lock137*138* @lock: Pointer to a struct ttm_lock139* @interruptible: Interruptible sleeping while waiting for a lock.140*141* Takes the lock in write mode.142* Returns:143* -ERESTARTSYS If interrupted by a signal and interruptible is true.144*/145extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);146147/**148* ttm_lock_downgrade149*150* @lock: Pointer to a struct ttm_lock151*152* Downgrades a write lock to a read lock.153*/154extern void ttm_lock_downgrade(struct ttm_lock *lock);155156/**157* ttm_suspend_lock158*159* @lock: Pointer to a struct ttm_lock160*161* Takes the lock in suspend mode. Excludes read and write mode.162*/163extern void ttm_suspend_lock(struct ttm_lock *lock);164165/**166* ttm_suspend_unlock167*168* @lock: Pointer to a struct ttm_lock169*170* Releases a suspend lock171*/172extern void ttm_suspend_unlock(struct ttm_lock *lock);173174/**175* ttm_vt_lock176*177* @lock: Pointer to a struct ttm_lock178* @interruptible: Interruptible sleeping while waiting for a lock.179* @tfile: Pointer to a struct ttm_object_file to register the lock with.180*181* Takes the lock in vt mode.182* Returns:183* -ERESTARTSYS If interrupted by a signal and interruptible is true.184* -ENOMEM: Out of memory when locking.185*/186extern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible,187struct ttm_object_file *tfile);188189/**190* ttm_vt_unlock191*192* @lock: Pointer to a struct ttm_lock193*194* Releases a vt lock.195* Returns:196* -EINVAL If the lock was not held.197*/198extern int ttm_vt_unlock(struct ttm_lock *lock);199200/**201* ttm_write_unlock202*203* @lock: Pointer to a struct ttm_lock204*205* Releases a write lock.206*/207extern void ttm_write_unlock(struct ttm_lock *lock);208209/**210* ttm_write_lock211*212* @lock: Pointer to a struct ttm_lock213* @interruptible: Interruptible sleeping while waiting for a lock.214*215* Takes the lock in write mode.216* Returns:217* -ERESTARTSYS If interrupted by a signal and interruptible is true.218*/219extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);220221/**222* ttm_lock_set_kill223*224* @lock: Pointer to a struct ttm_lock225* @val: Boolean whether to kill processes taking the lock.226* @signal: Signal to send to the process taking the lock.227*228* The kill-when-taking-lock functionality is used to kill processes that keep229* on using the TTM functionality when its resources has been taken down, for230* example when the X server exits. A typical sequence would look like this:231* - X server takes lock in write mode.232* - ttm_lock_set_kill() is called with @val set to true.233* - As part of X server exit, TTM resources are taken down.234* - X server releases the lock on file release.235* - Another dri client wants to render, takes the lock and is killed.236*237*/238static inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val,239int signal)240{241lock->kill_takers = val;242if (val)243lock->signal = signal;244}245246#endif247248249