[PATCH] drm/ttm: move ttm_lock.c to drm/vmwgfx

Thomas Hellström thomas at shipmail.org
Mon Dec 17 14:05:58 PST 2012


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=n. 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

<mlankhorst> but seriously, ttm_lock is best left undocumented since
nobody should use that unholy thing..
<danvet> agreed ;-)
<danvet> imo we should shovel that under drm/vmwgfx ...
<airlied> amen
<airlied> that thing scares me
<danvet> 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öm <thomas at shipmail.org> 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 probably
>> 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 suffer.
>>
>> The main use cases are:
>>
>> 1) If we change master, clients of other masters need to be locked out from
>> 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 patch
>> 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.
>>>
>>> <mlankhorst> but seriously, ttm_lock is best left undocumented since
>>> nobody should use that unholy thing..
>>> <danvet> agreed ;-)
>>> <danvet> imo we should shovel that under drm/vmwgfx ...
>>> <airlied> amen
>>> <airlied> that thing scares me
>>> <danvet> out of sight, out of mind ...
>>>
>>> Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
>>> ---
>>>    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 := -Iinclude/drm
>>>    ttm-y := 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 obtaining
>>> 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 ANY
>>> 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 <thellstrom-at-vmware-dot-com>
>>> - */
>>> -
>>> -#include <drm/ttm/ttm_lock.h>
>>> -#include <drm/ttm/ttm_module.h>
>>> -#include <linux/atomic.h>
>>> -#include <linux/errno.h>
>>> -#include <linux/wait.h>
>>> -#include <linux/sched.h>
>>> -#include <linux/module.h>
>>> -
>>> -#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 = 0;
>>> -       lock->flags = 0;
>>> -       lock->kill_takers = false;
>>> -       lock->signal = SIGKILL;
>>> -}
>>> -EXPORT_SYMBOL(ttm_lock_init);
>>> -
>>> -void ttm_read_unlock(struct ttm_lock *lock)
>>> -{
>>> -       spin_lock(&lock->lock);
>>> -       if (--lock->rw == 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 = 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 >= 0 && lock->flags == 0) {
>>> -               ++lock->rw;
>>> -               locked = true;
>>> -       }
>>> -       spin_unlock(&lock->lock);
>>> -       return locked;
>>> -}
>>> -
>>> -int ttm_read_lock(struct ttm_lock *lock, bool interruptible)
>>> -{
>>> -       int ret = 0;
>>> -
>>> -       if (interruptible)
>>> -               ret = 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 = true;
>>> -
>>> -       *locked = 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 >= 0 && lock->flags == 0) {
>>> -               ++lock->rw;
>>> -               block = false;
>>> -               *locked = true;
>>> -       } else if (lock->flags == 0) {
>>> -               block = false;
>>> -       }
>>> -       spin_unlock(&lock->lock);
>>> -
>>> -       return !block;
>>> -}
>>> -
>>> -int ttm_read_trylock(struct ttm_lock *lock, bool interruptible)
>>> -{
>>> -       int ret = 0;
>>> -       bool locked;
>>> -
>>> -       if (interruptible)
>>> -               ret = wait_event_interruptible
>>> -                       (lock->queue, __ttm_read_trylock(lock, &locked));
>>> -       else
>>> -               wait_event(lock->queue, __ttm_read_trylock(lock,
>>> &locked));
>>> -
>>> -       if (unlikely(ret != 0)) {
>>> -               BUG_ON(locked);
>>> -               return ret;
>>> -       }
>>> -
>>> -       return (locked) ? 0 : -EBUSY;
>>> -}
>>> -
>>> -void ttm_write_unlock(struct ttm_lock *lock)
>>> -{
>>> -       spin_lock(&lock->lock);
>>> -       lock->rw = 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 = 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 == 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDING) ==
>>> 0)) {
>>> -               lock->rw = -1;
>>> -               lock->flags &= ~TTM_WRITE_LOCK_PENDING;
>>> -               locked = true;
>>> -       } else {
>>> -               lock->flags |= TTM_WRITE_LOCK_PENDING;
>>> -       }
>>> -       spin_unlock(&lock->lock);
>>> -       return locked;
>>> -}
>>> -
>>> -int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
>>> -{
>>> -       int ret = 0;
>>> -
>>> -       if (interruptible) {
>>> -               ret = wait_event_interruptible(lock->queue,
>>> -                                              __ttm_write_lock(lock));
>>> -               if (unlikely(ret != 0)) {
>>> -                       spin_lock(&lock->lock);
>>> -                       lock->flags &= ~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 = 1;
>>> -       wake_up_all(&lock->queue);
>>> -       spin_unlock(&lock->lock);
>>> -}
>>> -
>>> -static int __ttm_vt_unlock(struct ttm_lock *lock)
>>> -{
>>> -       int ret = 0;
>>> -
>>> -       spin_lock(&lock->lock);
>>> -       if (unlikely(!(lock->flags & TTM_VT_LOCK)))
>>> -               ret = -EINVAL;
>>> -       lock->flags &= ~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 = *p_base;
>>> -       struct ttm_lock *lock = container_of(base, struct ttm_lock, base);
>>> -       int ret;
>>> -
>>> -       *p_base = NULL;
>>> -       ret = __ttm_vt_unlock(lock);
>>> -       BUG_ON(ret != 0);
>>> -}
>>> -
>>> -static bool __ttm_vt_lock(struct ttm_lock *lock)
>>> -{
>>> -       bool locked = false;
>>> -
>>> -       spin_lock(&lock->lock);
>>> -       if (lock->rw == 0) {
>>> -               lock->flags &= ~TTM_VT_LOCK_PENDING;
>>> -               lock->flags |= TTM_VT_LOCK;
>>> -               locked = true;
>>> -       } else {
>>> -               lock->flags |= 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 = 0;
>>> -
>>> -       if (interruptible) {
>>> -               ret = wait_event_interruptible(lock->queue,
>>> -                                              __ttm_vt_lock(lock));
>>> -               if (unlikely(ret != 0)) {
>>> -                       spin_lock(&lock->lock);
>>> -                       lock->flags &= ~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 = 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 = 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 &= ~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 = false;
>>> -
>>> -       spin_lock(&lock->lock);
>>> -       if (lock->rw == 0) {
>>> -               lock->flags &= ~TTM_SUSPEND_LOCK_PENDING;
>>> -               lock->flags |= TTM_SUSPEND_LOCK;
>>> -               locked = true;
>>> -       } else {
>>> -               lock->flags |= 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 := 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) := 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 obtaining
>>> 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 ANY
>>> 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 <thellstrom-at-vmware-dot-com>
>>> + */
>>> +
>>> +#include "ttm_lock.h"
>>> +#include <drm/ttm/ttm_module.h>
>>> +#include <linux/atomic.h>
>>> +#include <linux/errno.h>
>>> +#include <linux/wait.h>
>>> +#include <linux/sched.h>
>>> +#include <linux/module.h>
>>> +
>>> +#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 = 0;
>>> +       lock->flags = 0;
>>> +       lock->kill_takers = false;
>>> +       lock->signal = SIGKILL;
>>> +}
>>> +EXPORT_SYMBOL(ttm_lock_init);
>>> +
>>> +void ttm_read_unlock(struct ttm_lock *lock)
>>> +{
>>> +       spin_lock(&lock->lock);
>>> +       if (--lock->rw == 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 = 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 >= 0 && lock->flags == 0) {
>>> +               ++lock->rw;
>>> +               locked = true;
>>> +       }
>>> +       spin_unlock(&lock->lock);
>>> +       return locked;
>>> +}
>>> +
>>> +int ttm_read_lock(struct ttm_lock *lock, bool interruptible)
>>> +{
>>> +       int ret = 0;
>>> +
>>> +       if (interruptible)
>>> +               ret = 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 = true;
>>> +
>>> +       *locked = 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 >= 0 && lock->flags == 0) {
>>> +               ++lock->rw;
>>> +               block = false;
>>> +               *locked = true;
>>> +       } else if (lock->flags == 0) {
>>> +               block = false;
>>> +       }
>>> +       spin_unlock(&lock->lock);
>>> +
>>> +       return !block;
>>> +}
>>> +
>>> +int ttm_read_trylock(struct ttm_lock *lock, bool interruptible)
>>> +{
>>> +       int ret = 0;
>>> +       bool locked;
>>> +
>>> +       if (interruptible)
>>> +               ret = wait_event_interruptible
>>> +                       (lock->queue, __ttm_read_trylock(lock, &locked));
>>> +       else
>>> +               wait_event(lock->queue, __ttm_read_trylock(lock,
>>> &locked));
>>> +
>>> +       if (unlikely(ret != 0)) {
>>> +               BUG_ON(locked);
>>> +               return ret;
>>> +       }
>>> +
>>> +       return (locked) ? 0 : -EBUSY;
>>> +}
>>> +
>>> +void ttm_write_unlock(struct ttm_lock *lock)
>>> +{
>>> +       spin_lock(&lock->lock);
>>> +       lock->rw = 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 = 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 == 0 && ((lock->flags & ~TTM_WRITE_LOCK_PENDING) ==
>>> 0)) {
>>> +               lock->rw = -1;
>>> +               lock->flags &= ~TTM_WRITE_LOCK_PENDING;
>>> +               locked = true;
>>> +       } else {
>>> +               lock->flags |= TTM_WRITE_LOCK_PENDING;
>>> +       }
>>> +       spin_unlock(&lock->lock);
>>> +       return locked;
>>> +}
>>> +
>>> +int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
>>> +{
>>> +       int ret = 0;
>>> +
>>> +       if (interruptible) {
>>> +               ret = wait_event_interruptible(lock->queue,
>>> +                                              __ttm_write_lock(lock));
>>> +               if (unlikely(ret != 0)) {
>>> +                       spin_lock(&lock->lock);
>>> +                       lock->flags &= ~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 = 1;
>>> +       wake_up_all(&lock->queue);
>>> +       spin_unlock(&lock->lock);
>>> +}
>>> +
>>> +static int __ttm_vt_unlock(struct ttm_lock *lock)
>>> +{
>>> +       int ret = 0;
>>> +
>>> +       spin_lock(&lock->lock);
>>> +       if (unlikely(!(lock->flags & TTM_VT_LOCK)))
>>> +               ret = -EINVAL;
>>> +       lock->flags &= ~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 = *p_base;
>>> +       struct ttm_lock *lock = container_of(base, struct ttm_lock, base);
>>> +       int ret;
>>> +
>>> +       *p_base = NULL;
>>> +       ret = __ttm_vt_unlock(lock);
>>> +       BUG_ON(ret != 0);
>>> +}
>>> +
>>> +static bool __ttm_vt_lock(struct ttm_lock *lock)
>>> +{
>>> +       bool locked = false;
>>> +
>>> +       spin_lock(&lock->lock);
>>> +       if (lock->rw == 0) {
>>> +               lock->flags &= ~TTM_VT_LOCK_PENDING;
>>> +               lock->flags |= TTM_VT_LOCK;
>>> +               locked = true;
>>> +       } else {
>>> +               lock->flags |= 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 = 0;
>>> +
>>> +       if (interruptible) {
>>> +               ret = wait_event_interruptible(lock->queue,
>>> +                                              __ttm_vt_lock(lock));
>>> +               if (unlikely(ret != 0)) {
>>> +                       spin_lock(&lock->lock);
>>> +                       lock->flags &= ~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 = 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 = 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 &= ~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 = false;
>>> +
>>> +       spin_lock(&lock->lock);
>>> +       if (lock->rw == 0) {
>>> +               lock->flags &= ~TTM_SUSPEND_LOCK_PENDING;
>>> +               lock->flags |= TTM_SUSPEND_LOCK;
>>> +               locked = true;
>>> +       } else {
>>> +               lock->flags |= 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 obtaining
>>> 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 ANY
>>> 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 <thellstrom-at-vmware-dot-com>
>>> + */
>>> +
>>> +/** @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 for
>>> + * and executing suspend operations.
>>> + *
>>> + */
>>> +
>>> +#ifndef _TTM_LOCK_H_
>>> +#define _TTM_LOCK_H_
>>> +
>>> +#include <ttm/ttm_object.h>
>>> +#include <linux/wait.h>
>>> +#include <linux/atomic.h>
>>> +
>>> +/**
>>> + * 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 with.
>>> + *
>>> + * 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 that
>>> keep
>>> + * on using the TTM functionality when its resources has been taken down,
>>> 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 = val;
>>> +       if (val)
>>> +               lock->signal = 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 <linux/suspend.h>
>>>    #include <drm/ttm/ttm_bo_driver.h>
>>>    #include <drm/ttm/ttm_object.h>
>>> -#include <drm/ttm/ttm_lock.h>
>>> +#include "ttm_lock.h"
>>>    #include <drm/ttm/ttm_execbuf_util.h>
>>>    #include <drm/ttm/ttm_module.h>
>>>    #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 obtaining
>>> 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 ANY
>>> 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 <thellstrom-at-vmware-dot-com>
>>> - */
>>> -
>>> -/** @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 for
>>> - * and executing suspend operations.
>>> - *
>>> - */
>>> -
>>> -#ifndef _TTM_LOCK_H_
>>> -#define _TTM_LOCK_H_
>>> -
>>> -#include <ttm/ttm_object.h>
>>> -#include <linux/wait.h>
>>> -#include <linux/atomic.h>
>>> -
>>> -/**
>>> - * 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 with.
>>> - *
>>> - * 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 that
>>> keep
>>> - * on using the TTM functionality when its resources has been taken down,
>>> 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 = val;
>>> -       if (val)
>>> -               lock->signal = signal;
>>> -}
>>> -
>>> -#endif
>>
>>
>>
>
>





More information about the dri-devel mailing list