From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?ISO-8859-1?Q?Thomas_Hellstr=F6m?= Subject: Re: [PATCH] drm/ttm: move ttm_lock.c to drm/vmwgfx Date: Mon, 17 Dec 2012 23:05:58 +0100 Message-ID: <50CF9746.9090801@shipmail.org> References: <1355135186-20533-1-git-send-email-daniel.vetter@ffwll.ch> <50CB4B13.3080704@shipmail.org> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1"; Format="flowed" Content-Transfer-Encoding: quoted-printable Return-path: Received: from GOTHNET-SMTP2.gothnet.se (relay.gothnet.se [82.193.160.251]) by gabe.freedesktop.org (Postfix) with ESMTP id 61FCEE5E0E for ; Mon, 17 Dec 2012 14:06:05 -0800 (PST) In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org Errors-To: dri-devel-bounces+sf-dri-devel=m.gmane.org@lists.freedesktop.org To: Daniel Vetter Cc: DRI Development List-Id: dri-devel@lists.freedesktop.org On 12/14/12 7:50 PM, Daniel Vetter wrote: > Dude, you're seriously overshooting here. This patch isn't required > _at_ _all_ to do cross device sharing/reservations/whatever. We've > simply discussed TTM documentation in the context of Maartens work, > and I've suggested to include all the TTM kerneldoc into a nice > DocBook. That way the kerneldoc stuff gets at least check for correct > parameters and similar trivial stuff (core drm sucked royally in that > regard). So Maarten jabbed around, I and Dave joined in and since > besides vmwgfx nothing else uses it at all I've figured this can't > hurt. Well I appreciate the effort, but judging from the commit message, the = idea was to shovel the ttm lock under the carpet so that nobody else would use it, which would simplify the cross device reservation work, since it then wouldn't = have to take into account a client blocking all other clients from reserving. = A similar mechanism (not necessarily the TTM lock) needs to be in place for cross = reservation for item 3) listed below, otherwise a TTM driver wouldn't be able to defragment or to guarantee a = certain amount of graphics memory for command submission. (This was discussed in the = phone meeting in Copenhagen). > > If you think all the radeon/nouveau/i915/whatever drivers are screwed > up beyond repair and need to have the ttm_lock.c file where it is as a > stern reminder, I don't care one bit. Personally I think the right > solution is to abolish the drm master concept entirely and aim for > CONFIG_VT=3Dn. Insulation is a userspace problem which e.g. policykit or > whatever the latest thing is can do, or which should be solved for > real with per-process address spaces. Everything else smells too fishy > for me. So yeah, I don't think the fact that vmwgfx is the only driver > with a ->set_master and ->drop_master callback is a good sign, but > alas, not my driver and the core impact is negligible. The fact remains that as long as the current master concept is in place, = a drm client authenticated by one master (perhaps already terminated), is authenticated for all = masters, and IMO that's a pretty nasty security problem. That doesn't mean all the non-vmwgfx drivers are screwed up beyond = repair; it wouldn't be too hard to block clients belonging to other = masters than the current master in the DRM ioctl dispatcher, which would = have the additional benefit that the ttm lock can be reduced to a = read-write semaphore for cross-device reservation purposes. Finally, I'd like to add that IMHO disussions like but seriously, ttm_lock is best left undocumented since nobody should use that unholy thing.. agreed ;-) imo we should shovel that under drm/vmwgfx ... amen that thing scares me out of sight, out of mind ... where nobody apparently tried to figure out what purpose the code serves = and therefore failed to understand it are pretty unprofessional, and even more so when used as commit messages. > > Cheers, Daniel Cheers, Thomas > > On Fri, Dec 14, 2012 at 4:51 PM, Thomas Hellstr=F6m = wrote: >> Nack, >> >> I'm not against moving the TTM lock away, >> when a replacement strategy for the main use case is presented. >> >> but using wording like "unholy", "scares" just because there is a lack of >> understanding or because it gets in the way of implementing cross-device >> reservation is a really really bad idea, and FWIW I think it's an even >> better idea to refrain from such wording unless you completely understand >> the problem and have a better solution in place. >> >> No other driver uses it, probably simply because the driver writers prob= ably >> aren't aware of the use cases or don't implement parallel command >> submission. >> >> And if it weren't for the TTM lock, the cross device work wouldn't have = to >> consider the case where a client >> needs to lock out other reservers, and the cross-device design would suf= fer. >> >> The main use cases are: >> >> 1) If we change master, clients of other masters need to be locked out f= rom >> claiming memory resources (particularly VRAM). >> 2) If we're about to suspend and have cleaned VRAM, client's need to be >> stopped from validating VRAM buffer objects. >> 3) If a client needs access to the complete video memory space or need to >> defragment, it needs to lock out other reservers in a parallell command >> submission environment >> >> Now, present a better solution to those use cases, and I'll ack this pat= ch >> and implement that solution, or >> leave the TTM lock in place as a reminder that these things need to be >> considered, and that we should have a common solution to them. >> >> /Thomas >> >> >> >> >> >> On 12/10/12 11:26 AM, Daniel Vetter wrote: >>> ... it's the only user. Also move the header fil there. >>> >>> but seriously, ttm_lock is best left undocumented since >>> nobody should use that unholy thing.. >>> agreed ;-) >>> imo we should shovel that under drm/vmwgfx ... >>> amen >>> that thing scares me >>> out of sight, out of mind ... >>> >>> Signed-off-by: Daniel Vetter >>> --- >>> drivers/gpu/drm/ttm/Makefile | 2 +- >>> drivers/gpu/drm/ttm/ttm_lock.c | 310 >>> ----------------------------------- >>> drivers/gpu/drm/vmwgfx/Makefile | 2 +- >>> drivers/gpu/drm/vmwgfx/ttm_lock.c | 310 >>> +++++++++++++++++++++++++++++++++++ >>> drivers/gpu/drm/vmwgfx/ttm_lock.h | 247 +++++++++++++++++++++++++= +++ >>> drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 +- >>> include/drm/ttm/ttm_lock.h | 247 -------------------------= --- >>> 7 files changed, 560 insertions(+), 560 deletions(-) >>> delete mode 100644 drivers/gpu/drm/ttm/ttm_lock.c >>> create mode 100644 drivers/gpu/drm/vmwgfx/ttm_lock.c >>> create mode 100644 drivers/gpu/drm/vmwgfx/ttm_lock.h >>> delete mode 100644 include/drm/ttm/ttm_lock.h >>> >>> diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile >>> index b2b33dd..607a0b6 100644 >>> --- a/drivers/gpu/drm/ttm/Makefile >>> +++ b/drivers/gpu/drm/ttm/Makefile >>> @@ -4,7 +4,7 @@ >>> ccflags-y :=3D -Iinclude/drm >>> ttm-y :=3D ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ >>> ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ >>> - ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \ >>> + ttm_object.o ttm_execbuf_util.o ttm_page_alloc.o \ >>> ttm_bo_manager.o >>> ifeq ($(CONFIG_SWIOTLB),y) >>> diff --git a/drivers/gpu/drm/ttm/ttm_lock.c >>> b/drivers/gpu/drm/ttm/ttm_lock.c >>> deleted file mode 100644 >>> index 3daa9a3..0000000 >>> --- a/drivers/gpu/drm/ttm/ttm_lock.c >>> +++ /dev/null >>> @@ -1,310 +0,0 @@ >>> >>> -/*********************************************************************= ***** >>> - * >>> - * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA >>> - * All Rights Reserved. >>> - * >>> - * Permission is hereby granted, free of charge, to any person obtaini= ng >>> a >>> - * copy of this software and associated documentation files (the >>> - * "Software"), to deal in the Software without restriction, including >>> - * without limitation the rights to use, copy, modify, merge, publish, >>> - * distribute, sub license, and/or sell copies of the Software, and to >>> - * permit persons to whom the Software is furnished to do so, subject = to >>> - * the following conditions: >>> - * >>> - * The above copyright notice and this permission notice (including the >>> - * next paragraph) shall be included in all copies or substantial >>> portions >>> - * of the Software. >>> - * >>> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >>> EXPRESS OR >>> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >>> MERCHANTABILITY, >>> - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT >>> SHALL >>> - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR A= NY >>> CLAIM, >>> - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT = OR >>> - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE = OR >>> THE >>> - * USE OR OTHER DEALINGS IN THE SOFTWARE. >>> - * >>> - >>> ***********************************************************************= ***/ >>> -/* >>> - * Authors: Thomas Hellstrom >>> - */ >>> - >>> -#include >>> -#include >>> -#include >>> -#include >>> -#include >>> -#include >>> -#include >>> - >>> -#define TTM_WRITE_LOCK_PENDING (1 << 0) >>> -#define TTM_VT_LOCK_PENDING (1 << 1) >>> -#define TTM_SUSPEND_LOCK_PENDING (1 << 2) >>> -#define TTM_VT_LOCK (1 << 3) >>> -#define TTM_SUSPEND_LOCK (1 << 4) >>> - >>> -void ttm_lock_init(struct ttm_lock *lock) >>> -{ >>> - spin_lock_init(&lock->lock); >>> - init_waitqueue_head(&lock->queue); >>> - lock->rw =3D 0; >>> - lock->flags =3D 0; >>> - lock->kill_takers =3D false; >>> - lock->signal =3D SIGKILL; >>> -} >>> -EXPORT_SYMBOL(ttm_lock_init); >>> - >>> -void ttm_read_unlock(struct ttm_lock *lock) >>> -{ >>> - spin_lock(&lock->lock); >>> - if (--lock->rw =3D=3D 0) >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> -} >>> -EXPORT_SYMBOL(ttm_read_unlock); >>> - >>> -static bool __ttm_read_lock(struct ttm_lock *lock) >>> -{ >>> - bool locked =3D false; >>> - >>> - spin_lock(&lock->lock); >>> - if (unlikely(lock->kill_takers)) { >>> - send_sig(lock->signal, current, 0); >>> - spin_unlock(&lock->lock); >>> - return false; >>> - } >>> - if (lock->rw >=3D 0 && lock->flags =3D=3D 0) { >>> - ++lock->rw; >>> - locked =3D true; >>> - } >>> - spin_unlock(&lock->lock); >>> - return locked; >>> -} >>> - >>> -int ttm_read_lock(struct ttm_lock *lock, bool interruptible) >>> -{ >>> - int ret =3D 0; >>> - >>> - if (interruptible) >>> - ret =3D wait_event_interruptible(lock->queue, >>> - __ttm_read_lock(lock)); >>> - else >>> - wait_event(lock->queue, __ttm_read_lock(lock)); >>> - return ret; >>> -} >>> -EXPORT_SYMBOL(ttm_read_lock); >>> - >>> -static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked) >>> -{ >>> - bool block =3D true; >>> - >>> - *locked =3D false; >>> - >>> - spin_lock(&lock->lock); >>> - if (unlikely(lock->kill_takers)) { >>> - send_sig(lock->signal, current, 0); >>> - spin_unlock(&lock->lock); >>> - return false; >>> - } >>> - if (lock->rw >=3D 0 && lock->flags =3D=3D 0) { >>> - ++lock->rw; >>> - block =3D false; >>> - *locked =3D true; >>> - } else if (lock->flags =3D=3D 0) { >>> - block =3D false; >>> - } >>> - spin_unlock(&lock->lock); >>> - >>> - return !block; >>> -} >>> - >>> -int ttm_read_trylock(struct ttm_lock *lock, bool interruptible) >>> -{ >>> - int ret =3D 0; >>> - bool locked; >>> - >>> - if (interruptible) >>> - ret =3D wait_event_interruptible >>> - (lock->queue, __ttm_read_trylock(lock, &locked)= ); >>> - else >>> - wait_event(lock->queue, __ttm_read_trylock(lock, >>> &locked)); >>> - >>> - if (unlikely(ret !=3D 0)) { >>> - BUG_ON(locked); >>> - return ret; >>> - } >>> - >>> - return (locked) ? 0 : -EBUSY; >>> -} >>> - >>> -void ttm_write_unlock(struct ttm_lock *lock) >>> -{ >>> - spin_lock(&lock->lock); >>> - lock->rw =3D 0; >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> -} >>> -EXPORT_SYMBOL(ttm_write_unlock); >>> - >>> -static bool __ttm_write_lock(struct ttm_lock *lock) >>> -{ >>> - bool locked =3D false; >>> - >>> - spin_lock(&lock->lock); >>> - if (unlikely(lock->kill_takers)) { >>> - send_sig(lock->signal, current, 0); >>> - spin_unlock(&lock->lock); >>> - return false; >>> - } >>> - if (lock->rw =3D=3D 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDIN= G) =3D=3D >>> 0)) { >>> - lock->rw =3D -1; >>> - lock->flags &=3D ~TTM_WRITE_LOCK_PENDING; >>> - locked =3D true; >>> - } else { >>> - lock->flags |=3D TTM_WRITE_LOCK_PENDING; >>> - } >>> - spin_unlock(&lock->lock); >>> - return locked; >>> -} >>> - >>> -int ttm_write_lock(struct ttm_lock *lock, bool interruptible) >>> -{ >>> - int ret =3D 0; >>> - >>> - if (interruptible) { >>> - ret =3D wait_event_interruptible(lock->queue, >>> - __ttm_write_lock(lock)); >>> - if (unlikely(ret !=3D 0)) { >>> - spin_lock(&lock->lock); >>> - lock->flags &=3D ~TTM_WRITE_LOCK_PENDING; >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> - } >>> - } else >>> - wait_event(lock->queue, __ttm_read_lock(lock)); >>> - >>> - return ret; >>> -} >>> -EXPORT_SYMBOL(ttm_write_lock); >>> - >>> -void ttm_write_lock_downgrade(struct ttm_lock *lock) >>> -{ >>> - spin_lock(&lock->lock); >>> - lock->rw =3D 1; >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> -} >>> - >>> -static int __ttm_vt_unlock(struct ttm_lock *lock) >>> -{ >>> - int ret =3D 0; >>> - >>> - spin_lock(&lock->lock); >>> - if (unlikely(!(lock->flags & TTM_VT_LOCK))) >>> - ret =3D -EINVAL; >>> - lock->flags &=3D ~TTM_VT_LOCK; >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> - >>> - return ret; >>> -} >>> - >>> -static void ttm_vt_lock_remove(struct ttm_base_object **p_base) >>> -{ >>> - struct ttm_base_object *base =3D *p_base; >>> - struct ttm_lock *lock =3D container_of(base, struct ttm_lock, b= ase); >>> - int ret; >>> - >>> - *p_base =3D NULL; >>> - ret =3D __ttm_vt_unlock(lock); >>> - BUG_ON(ret !=3D 0); >>> -} >>> - >>> -static bool __ttm_vt_lock(struct ttm_lock *lock) >>> -{ >>> - bool locked =3D false; >>> - >>> - spin_lock(&lock->lock); >>> - if (lock->rw =3D=3D 0) { >>> - lock->flags &=3D ~TTM_VT_LOCK_PENDING; >>> - lock->flags |=3D TTM_VT_LOCK; >>> - locked =3D true; >>> - } else { >>> - lock->flags |=3D TTM_VT_LOCK_PENDING; >>> - } >>> - spin_unlock(&lock->lock); >>> - return locked; >>> -} >>> - >>> -int ttm_vt_lock(struct ttm_lock *lock, >>> - bool interruptible, >>> - struct ttm_object_file *tfile) >>> -{ >>> - int ret =3D 0; >>> - >>> - if (interruptible) { >>> - ret =3D wait_event_interruptible(lock->queue, >>> - __ttm_vt_lock(lock)); >>> - if (unlikely(ret !=3D 0)) { >>> - spin_lock(&lock->lock); >>> - lock->flags &=3D ~TTM_VT_LOCK_PENDING; >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> - return ret; >>> - } >>> - } else >>> - wait_event(lock->queue, __ttm_vt_lock(lock)); >>> - >>> - /* >>> - * Add a base-object, the destructor of which will >>> - * make sure the lock is released if the client dies >>> - * while holding it. >>> - */ >>> - >>> - ret =3D ttm_base_object_init(tfile, &lock->base, false, >>> - ttm_lock_type, &ttm_vt_lock_remove, >>> NULL); >>> - if (ret) >>> - (void)__ttm_vt_unlock(lock); >>> - else >>> - lock->vt_holder =3D tfile; >>> - >>> - return ret; >>> -} >>> -EXPORT_SYMBOL(ttm_vt_lock); >>> - >>> -int ttm_vt_unlock(struct ttm_lock *lock) >>> -{ >>> - return ttm_ref_object_base_unref(lock->vt_holder, >>> - lock->base.hash.key, >>> TTM_REF_USAGE); >>> -} >>> -EXPORT_SYMBOL(ttm_vt_unlock); >>> - >>> -void ttm_suspend_unlock(struct ttm_lock *lock) >>> -{ >>> - spin_lock(&lock->lock); >>> - lock->flags &=3D ~TTM_SUSPEND_LOCK; >>> - wake_up_all(&lock->queue); >>> - spin_unlock(&lock->lock); >>> -} >>> -EXPORT_SYMBOL(ttm_suspend_unlock); >>> - >>> -static bool __ttm_suspend_lock(struct ttm_lock *lock) >>> -{ >>> - bool locked =3D false; >>> - >>> - spin_lock(&lock->lock); >>> - if (lock->rw =3D=3D 0) { >>> - lock->flags &=3D ~TTM_SUSPEND_LOCK_PENDING; >>> - lock->flags |=3D TTM_SUSPEND_LOCK; >>> - locked =3D true; >>> - } else { >>> - lock->flags |=3D TTM_SUSPEND_LOCK_PENDING; >>> - } >>> - spin_unlock(&lock->lock); >>> - return locked; >>> -} >>> - >>> -void ttm_suspend_lock(struct ttm_lock *lock) >>> -{ >>> - wait_event(lock->queue, __ttm_suspend_lock(lock)); >>> -} >>> -EXPORT_SYMBOL(ttm_suspend_lock); >>> diff --git a/drivers/gpu/drm/vmwgfx/Makefile >>> b/drivers/gpu/drm/vmwgfx/Makefile >>> index 586869c..74bd973 100644 >>> --- a/drivers/gpu/drm/vmwgfx/Makefile >>> +++ b/drivers/gpu/drm/vmwgfx/Makefile >>> @@ -5,6 +5,6 @@ vmwgfx-y :=3D vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o >>> vmwgfx_drv.o \ >>> vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer= .o \ >>> vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ >>> vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \ >>> - vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o >>> + vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o ttm_lock.o >>> obj-$(CONFIG_DRM_VMWGFX) :=3D vmwgfx.o >>> diff --git a/drivers/gpu/drm/vmwgfx/ttm_lock.c >>> b/drivers/gpu/drm/vmwgfx/ttm_lock.c >>> new file mode 100644 >>> index 0000000..c859427 >>> --- /dev/null >>> +++ b/drivers/gpu/drm/vmwgfx/ttm_lock.c >>> @@ -0,0 +1,310 @@ >>> >>> +/*********************************************************************= ***** >>> + * >>> + * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA >>> + * All Rights Reserved. >>> + * >>> + * Permission is hereby granted, free of charge, to any person obtaini= ng >>> a >>> + * copy of this software and associated documentation files (the >>> + * "Software"), to deal in the Software without restriction, including >>> + * without limitation the rights to use, copy, modify, merge, publish, >>> + * distribute, sub license, and/or sell copies of the Software, and to >>> + * permit persons to whom the Software is furnished to do so, subject = to >>> + * the following conditions: >>> + * >>> + * The above copyright notice and this permission notice (including the >>> + * next paragraph) shall be included in all copies or substantial >>> portions >>> + * of the Software. >>> + * >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >>> EXPRESS OR >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >>> MERCHANTABILITY, >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT >>> SHALL >>> + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR A= NY >>> CLAIM, >>> + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT = OR >>> + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE = OR >>> THE >>> + * USE OR OTHER DEALINGS IN THE SOFTWARE. >>> + * >>> + >>> ***********************************************************************= ***/ >>> +/* >>> + * Authors: Thomas Hellstrom >>> + */ >>> + >>> +#include "ttm_lock.h" >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define TTM_WRITE_LOCK_PENDING (1 << 0) >>> +#define TTM_VT_LOCK_PENDING (1 << 1) >>> +#define TTM_SUSPEND_LOCK_PENDING (1 << 2) >>> +#define TTM_VT_LOCK (1 << 3) >>> +#define TTM_SUSPEND_LOCK (1 << 4) >>> + >>> +void ttm_lock_init(struct ttm_lock *lock) >>> +{ >>> + spin_lock_init(&lock->lock); >>> + init_waitqueue_head(&lock->queue); >>> + lock->rw =3D 0; >>> + lock->flags =3D 0; >>> + lock->kill_takers =3D false; >>> + lock->signal =3D SIGKILL; >>> +} >>> +EXPORT_SYMBOL(ttm_lock_init); >>> + >>> +void ttm_read_unlock(struct ttm_lock *lock) >>> +{ >>> + spin_lock(&lock->lock); >>> + if (--lock->rw =3D=3D 0) >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> +} >>> +EXPORT_SYMBOL(ttm_read_unlock); >>> + >>> +static bool __ttm_read_lock(struct ttm_lock *lock) >>> +{ >>> + bool locked =3D false; >>> + >>> + spin_lock(&lock->lock); >>> + if (unlikely(lock->kill_takers)) { >>> + send_sig(lock->signal, current, 0); >>> + spin_unlock(&lock->lock); >>> + return false; >>> + } >>> + if (lock->rw >=3D 0 && lock->flags =3D=3D 0) { >>> + ++lock->rw; >>> + locked =3D true; >>> + } >>> + spin_unlock(&lock->lock); >>> + return locked; >>> +} >>> + >>> +int ttm_read_lock(struct ttm_lock *lock, bool interruptible) >>> +{ >>> + int ret =3D 0; >>> + >>> + if (interruptible) >>> + ret =3D wait_event_interruptible(lock->queue, >>> + __ttm_read_lock(lock)); >>> + else >>> + wait_event(lock->queue, __ttm_read_lock(lock)); >>> + return ret; >>> +} >>> +EXPORT_SYMBOL(ttm_read_lock); >>> + >>> +static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked) >>> +{ >>> + bool block =3D true; >>> + >>> + *locked =3D false; >>> + >>> + spin_lock(&lock->lock); >>> + if (unlikely(lock->kill_takers)) { >>> + send_sig(lock->signal, current, 0); >>> + spin_unlock(&lock->lock); >>> + return false; >>> + } >>> + if (lock->rw >=3D 0 && lock->flags =3D=3D 0) { >>> + ++lock->rw; >>> + block =3D false; >>> + *locked =3D true; >>> + } else if (lock->flags =3D=3D 0) { >>> + block =3D false; >>> + } >>> + spin_unlock(&lock->lock); >>> + >>> + return !block; >>> +} >>> + >>> +int ttm_read_trylock(struct ttm_lock *lock, bool interruptible) >>> +{ >>> + int ret =3D 0; >>> + bool locked; >>> + >>> + if (interruptible) >>> + ret =3D wait_event_interruptible >>> + (lock->queue, __ttm_read_trylock(lock, &locked)= ); >>> + else >>> + wait_event(lock->queue, __ttm_read_trylock(lock, >>> &locked)); >>> + >>> + if (unlikely(ret !=3D 0)) { >>> + BUG_ON(locked); >>> + return ret; >>> + } >>> + >>> + return (locked) ? 0 : -EBUSY; >>> +} >>> + >>> +void ttm_write_unlock(struct ttm_lock *lock) >>> +{ >>> + spin_lock(&lock->lock); >>> + lock->rw =3D 0; >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> +} >>> +EXPORT_SYMBOL(ttm_write_unlock); >>> + >>> +static bool __ttm_write_lock(struct ttm_lock *lock) >>> +{ >>> + bool locked =3D false; >>> + >>> + spin_lock(&lock->lock); >>> + if (unlikely(lock->kill_takers)) { >>> + send_sig(lock->signal, current, 0); >>> + spin_unlock(&lock->lock); >>> + return false; >>> + } >>> + if (lock->rw =3D=3D 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDIN= G) =3D=3D >>> 0)) { >>> + lock->rw =3D -1; >>> + lock->flags &=3D ~TTM_WRITE_LOCK_PENDING; >>> + locked =3D true; >>> + } else { >>> + lock->flags |=3D TTM_WRITE_LOCK_PENDING; >>> + } >>> + spin_unlock(&lock->lock); >>> + return locked; >>> +} >>> + >>> +int ttm_write_lock(struct ttm_lock *lock, bool interruptible) >>> +{ >>> + int ret =3D 0; >>> + >>> + if (interruptible) { >>> + ret =3D wait_event_interruptible(lock->queue, >>> + __ttm_write_lock(lock)); >>> + if (unlikely(ret !=3D 0)) { >>> + spin_lock(&lock->lock); >>> + lock->flags &=3D ~TTM_WRITE_LOCK_PENDING; >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> + } >>> + } else >>> + wait_event(lock->queue, __ttm_read_lock(lock)); >>> + >>> + return ret; >>> +} >>> +EXPORT_SYMBOL(ttm_write_lock); >>> + >>> +void ttm_write_lock_downgrade(struct ttm_lock *lock) >>> +{ >>> + spin_lock(&lock->lock); >>> + lock->rw =3D 1; >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> +} >>> + >>> +static int __ttm_vt_unlock(struct ttm_lock *lock) >>> +{ >>> + int ret =3D 0; >>> + >>> + spin_lock(&lock->lock); >>> + if (unlikely(!(lock->flags & TTM_VT_LOCK))) >>> + ret =3D -EINVAL; >>> + lock->flags &=3D ~TTM_VT_LOCK; >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> + >>> + return ret; >>> +} >>> + >>> +static void ttm_vt_lock_remove(struct ttm_base_object **p_base) >>> +{ >>> + struct ttm_base_object *base =3D *p_base; >>> + struct ttm_lock *lock =3D container_of(base, struct ttm_lock, b= ase); >>> + int ret; >>> + >>> + *p_base =3D NULL; >>> + ret =3D __ttm_vt_unlock(lock); >>> + BUG_ON(ret !=3D 0); >>> +} >>> + >>> +static bool __ttm_vt_lock(struct ttm_lock *lock) >>> +{ >>> + bool locked =3D false; >>> + >>> + spin_lock(&lock->lock); >>> + if (lock->rw =3D=3D 0) { >>> + lock->flags &=3D ~TTM_VT_LOCK_PENDING; >>> + lock->flags |=3D TTM_VT_LOCK; >>> + locked =3D true; >>> + } else { >>> + lock->flags |=3D TTM_VT_LOCK_PENDING; >>> + } >>> + spin_unlock(&lock->lock); >>> + return locked; >>> +} >>> + >>> +int ttm_vt_lock(struct ttm_lock *lock, >>> + bool interruptible, >>> + struct ttm_object_file *tfile) >>> +{ >>> + int ret =3D 0; >>> + >>> + if (interruptible) { >>> + ret =3D wait_event_interruptible(lock->queue, >>> + __ttm_vt_lock(lock)); >>> + if (unlikely(ret !=3D 0)) { >>> + spin_lock(&lock->lock); >>> + lock->flags &=3D ~TTM_VT_LOCK_PENDING; >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> + return ret; >>> + } >>> + } else >>> + wait_event(lock->queue, __ttm_vt_lock(lock)); >>> + >>> + /* >>> + * Add a base-object, the destructor of which will >>> + * make sure the lock is released if the client dies >>> + * while holding it. >>> + */ >>> + >>> + ret =3D ttm_base_object_init(tfile, &lock->base, false, >>> + ttm_lock_type, &ttm_vt_lock_remove, >>> NULL); >>> + if (ret) >>> + (void)__ttm_vt_unlock(lock); >>> + else >>> + lock->vt_holder =3D tfile; >>> + >>> + return ret; >>> +} >>> +EXPORT_SYMBOL(ttm_vt_lock); >>> + >>> +int ttm_vt_unlock(struct ttm_lock *lock) >>> +{ >>> + return ttm_ref_object_base_unref(lock->vt_holder, >>> + lock->base.hash.key, >>> TTM_REF_USAGE); >>> +} >>> +EXPORT_SYMBOL(ttm_vt_unlock); >>> + >>> +void ttm_suspend_unlock(struct ttm_lock *lock) >>> +{ >>> + spin_lock(&lock->lock); >>> + lock->flags &=3D ~TTM_SUSPEND_LOCK; >>> + wake_up_all(&lock->queue); >>> + spin_unlock(&lock->lock); >>> +} >>> +EXPORT_SYMBOL(ttm_suspend_unlock); >>> + >>> +static bool __ttm_suspend_lock(struct ttm_lock *lock) >>> +{ >>> + bool locked =3D false; >>> + >>> + spin_lock(&lock->lock); >>> + if (lock->rw =3D=3D 0) { >>> + lock->flags &=3D ~TTM_SUSPEND_LOCK_PENDING; >>> + lock->flags |=3D TTM_SUSPEND_LOCK; >>> + locked =3D true; >>> + } else { >>> + lock->flags |=3D TTM_SUSPEND_LOCK_PENDING; >>> + } >>> + spin_unlock(&lock->lock); >>> + return locked; >>> +} >>> + >>> +void ttm_suspend_lock(struct ttm_lock *lock) >>> +{ >>> + wait_event(lock->queue, __ttm_suspend_lock(lock)); >>> +} >>> +EXPORT_SYMBOL(ttm_suspend_lock); >>> diff --git a/drivers/gpu/drm/vmwgfx/ttm_lock.h >>> b/drivers/gpu/drm/vmwgfx/ttm_lock.h >>> new file mode 100644 >>> index 0000000..2902beb >>> --- /dev/null >>> +++ b/drivers/gpu/drm/vmwgfx/ttm_lock.h >>> @@ -0,0 +1,247 @@ >>> >>> +/*********************************************************************= ***** >>> + * >>> + * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA >>> + * All Rights Reserved. >>> + * >>> + * Permission is hereby granted, free of charge, to any person obtaini= ng >>> a >>> + * copy of this software and associated documentation files (the >>> + * "Software"), to deal in the Software without restriction, including >>> + * without limitation the rights to use, copy, modify, merge, publish, >>> + * distribute, sub license, and/or sell copies of the Software, and to >>> + * permit persons to whom the Software is furnished to do so, subject = to >>> + * the following conditions: >>> + * >>> + * The above copyright notice and this permission notice (including the >>> + * next paragraph) shall be included in all copies or substantial >>> portions >>> + * of the Software. >>> + * >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >>> EXPRESS OR >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >>> MERCHANTABILITY, >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT >>> SHALL >>> + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR A= NY >>> CLAIM, >>> + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT = OR >>> + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE = OR >>> THE >>> + * USE OR OTHER DEALINGS IN THE SOFTWARE. >>> + * >>> + >>> ***********************************************************************= ***/ >>> +/* >>> + * Authors: Thomas Hellstrom >>> + */ >>> + >>> +/** @file ttm_lock.h >>> + * This file implements a simple replacement for the buffer manager use >>> + * of the DRM heavyweight hardware lock. >>> + * The lock is a read-write lock. Taking it in read mode and write mode >>> + * is relatively fast, and intended for in-kernel use only. >>> + * >>> + * The vt mode is used only when there is a need to block all >>> + * user-space processes from validating buffers. >>> + * It's allowed to leave kernel space with the vt lock held. >>> + * If a user-space process dies while having the vt-lock, >>> + * it will be released during the file descriptor release. The vt lock >>> + * excludes write lock and read lock. >>> + * >>> + * The suspend mode is used to lock out all TTM users when preparing f= or >>> + * and executing suspend operations. >>> + * >>> + */ >>> + >>> +#ifndef _TTM_LOCK_H_ >>> +#define _TTM_LOCK_H_ >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +/** >>> + * struct ttm_lock >>> + * >>> + * @base: ttm base object used solely to release the lock if the client >>> + * holding the lock dies. >>> + * @queue: Queue for processes waiting for lock change-of-status. >>> + * @lock: Spinlock protecting some lock members. >>> + * @rw: Read-write lock counter. Protected by @lock. >>> + * @flags: Lock state. Protected by @lock. >>> + * @kill_takers: Boolean whether to kill takers of the lock. >>> + * @signal: Signal to send when kill_takers is true. >>> + */ >>> + >>> +struct ttm_lock { >>> + struct ttm_base_object base; >>> + wait_queue_head_t queue; >>> + spinlock_t lock; >>> + int32_t rw; >>> + uint32_t flags; >>> + bool kill_takers; >>> + int signal; >>> + struct ttm_object_file *vt_holder; >>> +}; >>> + >>> + >>> +/** >>> + * ttm_lock_init >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * Initializes the lock. >>> + */ >>> +extern void ttm_lock_init(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_read_unlock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Releases a read lock. >>> + */ >>> +extern void ttm_read_unlock(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_read_lock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * @interruptible: Interruptible sleeping while waiting for a lock. >>> + * >>> + * Takes the lock in read mode. >>> + * Returns: >>> + * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> + */ >>> +extern int ttm_read_lock(struct ttm_lock *lock, bool interruptible); >>> + >>> +/** >>> + * ttm_read_trylock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * @interruptible: Interruptible sleeping while waiting for a lock. >>> + * >>> + * Tries to take the lock in read mode. If the lock is already held >>> + * in write mode, the function will return -EBUSY. If the lock is held >>> + * in vt or suspend mode, the function will sleep until these modes >>> + * are unlocked. >>> + * >>> + * Returns: >>> + * -EBUSY The lock was already held in write mode. >>> + * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> + */ >>> +extern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible); >>> + >>> +/** >>> + * ttm_write_unlock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Releases a write lock. >>> + */ >>> +extern void ttm_write_unlock(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_write_lock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * @interruptible: Interruptible sleeping while waiting for a lock. >>> + * >>> + * Takes the lock in write mode. >>> + * Returns: >>> + * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> + */ >>> +extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); >>> + >>> +/** >>> + * ttm_lock_downgrade >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Downgrades a write lock to a read lock. >>> + */ >>> +extern void ttm_lock_downgrade(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_suspend_lock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Takes the lock in suspend mode. Excludes read and write mode. >>> + */ >>> +extern void ttm_suspend_lock(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_suspend_unlock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Releases a suspend lock >>> + */ >>> +extern void ttm_suspend_unlock(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_vt_lock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * @interruptible: Interruptible sleeping while waiting for a lock. >>> + * @tfile: Pointer to a struct ttm_object_file to register the lock wi= th. >>> + * >>> + * Takes the lock in vt mode. >>> + * Returns: >>> + * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> + * -ENOMEM: Out of memory when locking. >>> + */ >>> +extern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible, >>> + struct ttm_object_file *tfile); >>> + >>> +/** >>> + * ttm_vt_unlock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Releases a vt lock. >>> + * Returns: >>> + * -EINVAL If the lock was not held. >>> + */ >>> +extern int ttm_vt_unlock(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_write_unlock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * >>> + * Releases a write lock. >>> + */ >>> +extern void ttm_write_unlock(struct ttm_lock *lock); >>> + >>> +/** >>> + * ttm_write_lock >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * @interruptible: Interruptible sleeping while waiting for a lock. >>> + * >>> + * Takes the lock in write mode. >>> + * Returns: >>> + * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> + */ >>> +extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); >>> + >>> +/** >>> + * ttm_lock_set_kill >>> + * >>> + * @lock: Pointer to a struct ttm_lock >>> + * @val: Boolean whether to kill processes taking the lock. >>> + * @signal: Signal to send to the process taking the lock. >>> + * >>> + * The kill-when-taking-lock functionality is used to kill processes t= hat >>> keep >>> + * on using the TTM functionality when its resources has been taken do= wn, >>> for >>> + * example when the X server exits. A typical sequence would look like >>> this: >>> + * - X server takes lock in write mode. >>> + * - ttm_lock_set_kill() is called with @val set to true. >>> + * - As part of X server exit, TTM resources are taken down. >>> + * - X server releases the lock on file release. >>> + * - Another dri client wants to render, takes the lock and is killed. >>> + * >>> + */ >>> +static inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val, >>> + int signal) >>> +{ >>> + lock->kill_takers =3D val; >>> + if (val) >>> + lock->signal =3D signal; >>> +} >>> + >>> +#endif >>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h >>> b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h >>> index 7c6f6e3..94e6de1 100644 >>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h >>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h >>> @@ -35,7 +35,7 @@ >>> #include >>> #include >>> #include >>> -#include >>> +#include "ttm_lock.h" >>> #include >>> #include >>> #include "vmwgfx_fence.h" >>> diff --git a/include/drm/ttm/ttm_lock.h b/include/drm/ttm/ttm_lock.h >>> deleted file mode 100644 >>> index 2902beb..0000000 >>> --- a/include/drm/ttm/ttm_lock.h >>> +++ /dev/null >>> @@ -1,247 +0,0 @@ >>> >>> -/*********************************************************************= ***** >>> - * >>> - * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA >>> - * All Rights Reserved. >>> - * >>> - * Permission is hereby granted, free of charge, to any person obtaini= ng >>> a >>> - * copy of this software and associated documentation files (the >>> - * "Software"), to deal in the Software without restriction, including >>> - * without limitation the rights to use, copy, modify, merge, publish, >>> - * distribute, sub license, and/or sell copies of the Software, and to >>> - * permit persons to whom the Software is furnished to do so, subject = to >>> - * the following conditions: >>> - * >>> - * The above copyright notice and this permission notice (including the >>> - * next paragraph) shall be included in all copies or substantial >>> portions >>> - * of the Software. >>> - * >>> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, >>> EXPRESS OR >>> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >>> MERCHANTABILITY, >>> - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT >>> SHALL >>> - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR A= NY >>> CLAIM, >>> - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT = OR >>> - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE = OR >>> THE >>> - * USE OR OTHER DEALINGS IN THE SOFTWARE. >>> - * >>> - >>> ***********************************************************************= ***/ >>> -/* >>> - * Authors: Thomas Hellstrom >>> - */ >>> - >>> -/** @file ttm_lock.h >>> - * This file implements a simple replacement for the buffer manager use >>> - * of the DRM heavyweight hardware lock. >>> - * The lock is a read-write lock. Taking it in read mode and write mode >>> - * is relatively fast, and intended for in-kernel use only. >>> - * >>> - * The vt mode is used only when there is a need to block all >>> - * user-space processes from validating buffers. >>> - * It's allowed to leave kernel space with the vt lock held. >>> - * If a user-space process dies while having the vt-lock, >>> - * it will be released during the file descriptor release. The vt lock >>> - * excludes write lock and read lock. >>> - * >>> - * The suspend mode is used to lock out all TTM users when preparing f= or >>> - * and executing suspend operations. >>> - * >>> - */ >>> - >>> -#ifndef _TTM_LOCK_H_ >>> -#define _TTM_LOCK_H_ >>> - >>> -#include >>> -#include >>> -#include >>> - >>> -/** >>> - * struct ttm_lock >>> - * >>> - * @base: ttm base object used solely to release the lock if the client >>> - * holding the lock dies. >>> - * @queue: Queue for processes waiting for lock change-of-status. >>> - * @lock: Spinlock protecting some lock members. >>> - * @rw: Read-write lock counter. Protected by @lock. >>> - * @flags: Lock state. Protected by @lock. >>> - * @kill_takers: Boolean whether to kill takers of the lock. >>> - * @signal: Signal to send when kill_takers is true. >>> - */ >>> - >>> -struct ttm_lock { >>> - struct ttm_base_object base; >>> - wait_queue_head_t queue; >>> - spinlock_t lock; >>> - int32_t rw; >>> - uint32_t flags; >>> - bool kill_takers; >>> - int signal; >>> - struct ttm_object_file *vt_holder; >>> -}; >>> - >>> - >>> -/** >>> - * ttm_lock_init >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * Initializes the lock. >>> - */ >>> -extern void ttm_lock_init(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_read_unlock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Releases a read lock. >>> - */ >>> -extern void ttm_read_unlock(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_read_lock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * @interruptible: Interruptible sleeping while waiting for a lock. >>> - * >>> - * Takes the lock in read mode. >>> - * Returns: >>> - * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> - */ >>> -extern int ttm_read_lock(struct ttm_lock *lock, bool interruptible); >>> - >>> -/** >>> - * ttm_read_trylock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * @interruptible: Interruptible sleeping while waiting for a lock. >>> - * >>> - * Tries to take the lock in read mode. If the lock is already held >>> - * in write mode, the function will return -EBUSY. If the lock is held >>> - * in vt or suspend mode, the function will sleep until these modes >>> - * are unlocked. >>> - * >>> - * Returns: >>> - * -EBUSY The lock was already held in write mode. >>> - * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> - */ >>> -extern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible); >>> - >>> -/** >>> - * ttm_write_unlock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Releases a write lock. >>> - */ >>> -extern void ttm_write_unlock(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_write_lock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * @interruptible: Interruptible sleeping while waiting for a lock. >>> - * >>> - * Takes the lock in write mode. >>> - * Returns: >>> - * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> - */ >>> -extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); >>> - >>> -/** >>> - * ttm_lock_downgrade >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Downgrades a write lock to a read lock. >>> - */ >>> -extern void ttm_lock_downgrade(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_suspend_lock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Takes the lock in suspend mode. Excludes read and write mode. >>> - */ >>> -extern void ttm_suspend_lock(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_suspend_unlock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Releases a suspend lock >>> - */ >>> -extern void ttm_suspend_unlock(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_vt_lock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * @interruptible: Interruptible sleeping while waiting for a lock. >>> - * @tfile: Pointer to a struct ttm_object_file to register the lock wi= th. >>> - * >>> - * Takes the lock in vt mode. >>> - * Returns: >>> - * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> - * -ENOMEM: Out of memory when locking. >>> - */ >>> -extern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible, >>> - struct ttm_object_file *tfile); >>> - >>> -/** >>> - * ttm_vt_unlock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Releases a vt lock. >>> - * Returns: >>> - * -EINVAL If the lock was not held. >>> - */ >>> -extern int ttm_vt_unlock(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_write_unlock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * >>> - * Releases a write lock. >>> - */ >>> -extern void ttm_write_unlock(struct ttm_lock *lock); >>> - >>> -/** >>> - * ttm_write_lock >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * @interruptible: Interruptible sleeping while waiting for a lock. >>> - * >>> - * Takes the lock in write mode. >>> - * Returns: >>> - * -ERESTARTSYS If interrupted by a signal and interruptible is true. >>> - */ >>> -extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible); >>> - >>> -/** >>> - * ttm_lock_set_kill >>> - * >>> - * @lock: Pointer to a struct ttm_lock >>> - * @val: Boolean whether to kill processes taking the lock. >>> - * @signal: Signal to send to the process taking the lock. >>> - * >>> - * The kill-when-taking-lock functionality is used to kill processes t= hat >>> keep >>> - * on using the TTM functionality when its resources has been taken do= wn, >>> for >>> - * example when the X server exits. A typical sequence would look like >>> this: >>> - * - X server takes lock in write mode. >>> - * - ttm_lock_set_kill() is called with @val set to true. >>> - * - As part of X server exit, TTM resources are taken down. >>> - * - X server releases the lock on file release. >>> - * - Another dri client wants to render, takes the lock and is killed. >>> - * >>> - */ >>> -static inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val, >>> - int signal) >>> -{ >>> - lock->kill_takers =3D val; >>> - if (val) >>> - lock->signal =3D signal; >>> -} >>> - >>> -#endif >> >> >> > >