diff mbox

[WW,02/13] drm/ttm: make ttm reservation calls behave like reservation calls

Message ID 1372333708-29884-3-git-send-email-maarten.lankhorst@canonical.com (mailing list archive)
State Accepted
Headers show

Commit Message

Maarten Lankhorst June 27, 2013, 11:48 a.m. UTC
This commit converts the source of the val_seq counter to
the ww_mutex api. The reservation objects are converted later,
because there is still a lockdep splat in nouveau that has to
resolved first.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
---
 drivers/gpu/drm/nouveau/nouveau_gem.c    | 38 ++++++++++++++-------
 drivers/gpu/drm/radeon/radeon.h          |  1 +
 drivers/gpu/drm/radeon/radeon_cs.c       | 18 +++++-----
 drivers/gpu/drm/radeon/radeon_object.c   |  5 +--
 drivers/gpu/drm/radeon/radeon_object.h   |  3 +-
 drivers/gpu/drm/radeon/radeon_uvd.c      | 27 +++++++--------
 drivers/gpu/drm/ttm/ttm_bo.c             | 50 +++++++++++++++++----------
 drivers/gpu/drm/ttm/ttm_execbuf_util.c   | 58 +++++++++++++++++---------------
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c  | 14 ++++----
 drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 23 ++++++++-----
 include/drm/ttm/ttm_bo_api.h             |  2 +-
 include/drm/ttm/ttm_bo_driver.h          | 32 +++++++++++++-----
 include/drm/ttm/ttm_execbuf_util.h       | 13 +++++--
 13 files changed, 172 insertions(+), 112 deletions(-)

Comments

Jerome Glisse June 27, 2013, 9:47 p.m. UTC | #1
On Thu, Jun 27, 2013 at 01:48:17PM +0200, Maarten Lankhorst wrote:
> This commit converts the source of the val_seq counter to
> the ww_mutex api. The reservation objects are converted later,
> because there is still a lockdep splat in nouveau that has to
> resolved first.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>

Reviewed-by: Jerome Glisse <jglisse@redhat.com>

> ---
>  drivers/gpu/drm/nouveau/nouveau_gem.c    | 38 ++++++++++++++-------
>  drivers/gpu/drm/radeon/radeon.h          |  1 +
>  drivers/gpu/drm/radeon/radeon_cs.c       | 18 +++++-----
>  drivers/gpu/drm/radeon/radeon_object.c   |  5 +--
>  drivers/gpu/drm/radeon/radeon_object.h   |  3 +-
>  drivers/gpu/drm/radeon/radeon_uvd.c      | 27 +++++++--------
>  drivers/gpu/drm/ttm/ttm_bo.c             | 50 +++++++++++++++++----------
>  drivers/gpu/drm/ttm/ttm_execbuf_util.c   | 58 +++++++++++++++++---------------
>  drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c  | 14 ++++----
>  drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 23 ++++++++-----
>  include/drm/ttm/ttm_bo_api.h             |  2 +-
>  include/drm/ttm/ttm_bo_driver.h          | 32 +++++++++++++-----
>  include/drm/ttm/ttm_execbuf_util.h       | 13 +++++--
>  13 files changed, 172 insertions(+), 112 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
> index 7054706..e35d468 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
> @@ -277,10 +277,12 @@ struct validate_op {
>  	struct list_head vram_list;
>  	struct list_head gart_list;
>  	struct list_head both_list;
> +	struct ww_acquire_ctx ticket;
>  };
>  
>  static void
> -validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
> +validate_fini_list(struct list_head *list, struct nouveau_fence *fence,
> +		   struct ww_acquire_ctx *ticket)
>  {
>  	struct list_head *entry, *tmp;
>  	struct nouveau_bo *nvbo;
> @@ -297,17 +299,24 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
>  
>  		list_del(&nvbo->entry);
>  		nvbo->reserved_by = NULL;
> -		ttm_bo_unreserve(&nvbo->bo);
> +		ttm_bo_unreserve_ticket(&nvbo->bo, ticket);
>  		drm_gem_object_unreference_unlocked(nvbo->gem);
>  	}
>  }
>  
>  static void
> -validate_fini(struct validate_op *op, struct nouveau_fence* fence)
> +validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence)
>  {
> -	validate_fini_list(&op->vram_list, fence);
> -	validate_fini_list(&op->gart_list, fence);
> -	validate_fini_list(&op->both_list, fence);
> +	validate_fini_list(&op->vram_list, fence, &op->ticket);
> +	validate_fini_list(&op->gart_list, fence, &op->ticket);
> +	validate_fini_list(&op->both_list, fence, &op->ticket);
> +}
> +
> +static void
> +validate_fini(struct validate_op *op, struct nouveau_fence *fence)
> +{
> +	validate_fini_no_ticket(op, fence);
> +	ww_acquire_fini(&op->ticket);
>  }
>  
>  static int
> @@ -317,13 +326,11 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
>  {
>  	struct nouveau_cli *cli = nouveau_cli(file_priv);
>  	struct drm_device *dev = chan->drm->dev;
> -	struct nouveau_drm *drm = nouveau_drm(dev);
> -	uint32_t sequence;
>  	int trycnt = 0;
>  	int ret, i;
>  	struct nouveau_bo *res_bo = NULL;
>  
> -	sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
> +	ww_acquire_init(&op->ticket, &reservation_ww_class);
>  retry:
>  	if (++trycnt > 100000) {
>  		NV_ERROR(cli, "%s failed and gave up.\n", __func__);
> @@ -338,6 +345,7 @@ retry:
>  		gem = drm_gem_object_lookup(dev, file_priv, b->handle);
>  		if (!gem) {
>  			NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
> +			ww_acquire_done(&op->ticket);
>  			validate_fini(op, NULL);
>  			return -ENOENT;
>  		}
> @@ -352,21 +360,23 @@ retry:
>  			NV_ERROR(cli, "multiple instances of buffer %d on "
>  				      "validation list\n", b->handle);
>  			drm_gem_object_unreference_unlocked(gem);
> +			ww_acquire_done(&op->ticket);
>  			validate_fini(op, NULL);
>  			return -EINVAL;
>  		}
>  
> -		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence);
> +		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, &op->ticket);
>  		if (ret) {
> -			validate_fini(op, NULL);
> +			validate_fini_no_ticket(op, NULL);
>  			if (unlikely(ret == -EAGAIN)) {
> -				sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
>  				ret = ttm_bo_reserve_slowpath(&nvbo->bo, true,
> -							      sequence);
> +							      &op->ticket);
>  				if (!ret)
>  					res_bo = nvbo;
>  			}
>  			if (unlikely(ret)) {
> +				ww_acquire_done(&op->ticket);
> +				ww_acquire_fini(&op->ticket);
>  				drm_gem_object_unreference_unlocked(gem);
>  				if (ret != -ERESTARTSYS)
>  					NV_ERROR(cli, "fail reserve\n");
> @@ -390,6 +400,7 @@ retry:
>  			NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
>  				 b->valid_domains);
>  			list_add_tail(&nvbo->entry, &op->both_list);
> +			ww_acquire_done(&op->ticket);
>  			validate_fini(op, NULL);
>  			return -EINVAL;
>  		}
> @@ -397,6 +408,7 @@ retry:
>  			goto retry;
>  	}
>  
> +	ww_acquire_done(&op->ticket);
>  	return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 142ce6c..eaf4ff5 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -883,6 +883,7 @@ struct radeon_cs_parser {
>  	u32			cs_flags;
>  	u32			ring;
>  	s32			priority;
> +	struct ww_acquire_ctx	ticket;
>  };
>  
>  extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
> diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
> index 7e265a5..8a91901 100644
> --- a/drivers/gpu/drm/radeon/radeon_cs.c
> +++ b/drivers/gpu/drm/radeon/radeon_cs.c
> @@ -106,7 +106,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
>  		radeon_bo_list_add_object(&p->relocs[i].lobj,
>  					  &p->validated);
>  	}
> -	return radeon_bo_list_validate(&p->validated, p->ring);
> +	return radeon_bo_list_validate(&p->ticket, &p->validated, p->ring);
>  }
>  
>  static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
> @@ -314,15 +314,17 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
>   * If error is set than unvalidate buffer, otherwise just free memory
>   * used by parsing context.
>   **/
> -static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
> +static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bool backoff)
>  {
>  	unsigned i;
>  
>  	if (!error) {
> -		ttm_eu_fence_buffer_objects(&parser->validated,
> +		ttm_eu_fence_buffer_objects(&parser->ticket,
> +					    &parser->validated,
>  					    parser->ib.fence);
> -	} else {
> -		ttm_eu_backoff_reservation(&parser->validated);
> +	} else if (backoff) {
> +		ttm_eu_backoff_reservation(&parser->ticket,
> +					   &parser->validated);
>  	}
>  
>  	if (parser->relocs != NULL) {
> @@ -535,7 +537,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
>  	r = radeon_cs_parser_init(&parser, data);
>  	if (r) {
>  		DRM_ERROR("Failed to initialize parser !\n");
> -		radeon_cs_parser_fini(&parser, r);
> +		radeon_cs_parser_fini(&parser, r, false);
>  		up_read(&rdev->exclusive_lock);
>  		r = radeon_cs_handle_lockup(rdev, r);
>  		return r;
> @@ -544,7 +546,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
>  	if (r) {
>  		if (r != -ERESTARTSYS)
>  			DRM_ERROR("Failed to parse relocation %d!\n", r);
> -		radeon_cs_parser_fini(&parser, r);
> +		radeon_cs_parser_fini(&parser, r, false);
>  		up_read(&rdev->exclusive_lock);
>  		r = radeon_cs_handle_lockup(rdev, r);
>  		return r;
> @@ -562,7 +564,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
>  		goto out;
>  	}
>  out:
> -	radeon_cs_parser_fini(&parser, r);
> +	radeon_cs_parser_fini(&parser, r, true);
>  	up_read(&rdev->exclusive_lock);
>  	r = radeon_cs_handle_lockup(rdev, r);
>  	return r;
> diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
> index 07af5a9..71287bb 100644
> --- a/drivers/gpu/drm/radeon/radeon_object.c
> +++ b/drivers/gpu/drm/radeon/radeon_object.c
> @@ -349,14 +349,15 @@ void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
>  	}
>  }
>  
> -int radeon_bo_list_validate(struct list_head *head, int ring)
> +int radeon_bo_list_validate(struct ww_acquire_ctx *ticket,
> +			    struct list_head *head, int ring)
>  {
>  	struct radeon_bo_list *lobj;
>  	struct radeon_bo *bo;
>  	u32 domain;
>  	int r;
>  
> -	r = ttm_eu_reserve_buffers(head);
> +	r = ttm_eu_reserve_buffers(ticket, head);
>  	if (unlikely(r != 0)) {
>  		return r;
>  	}
> diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
> index e2cb80a..3e62a3a 100644
> --- a/drivers/gpu/drm/radeon/radeon_object.h
> +++ b/drivers/gpu/drm/radeon/radeon_object.h
> @@ -128,7 +128,8 @@ extern int radeon_bo_init(struct radeon_device *rdev);
>  extern void radeon_bo_fini(struct radeon_device *rdev);
>  extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
>  				struct list_head *head);
> -extern int radeon_bo_list_validate(struct list_head *head, int ring);
> +extern int radeon_bo_list_validate(struct ww_acquire_ctx *ticket,
> +				   struct list_head *head, int ring);
>  extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
>  				struct vm_area_struct *vma);
>  extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
> diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
> index cad735d..0078cdf 100644
> --- a/drivers/gpu/drm/radeon/radeon_uvd.c
> +++ b/drivers/gpu/drm/radeon/radeon_uvd.c
> @@ -542,6 +542,7 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
>  			       struct radeon_fence **fence)
>  {
>  	struct ttm_validate_buffer tv;
> +	struct ww_acquire_ctx ticket;
>  	struct list_head head;
>  	struct radeon_ib ib;
>  	uint64_t addr;
> @@ -553,7 +554,7 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
>  	INIT_LIST_HEAD(&head);
>  	list_add(&tv.head, &head);
>  
> -	r = ttm_eu_reserve_buffers(&head);
> +	r = ttm_eu_reserve_buffers(&ticket, &head);
>  	if (r)
>  		return r;
>  
> @@ -561,16 +562,12 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
>  	radeon_uvd_force_into_uvd_segment(bo);
>  
>  	r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
> -	if (r) {
> -		ttm_eu_backoff_reservation(&head);
> -		return r;
> -	}
> +	if (r) 
> +		goto err;
>  
>  	r = radeon_ib_get(rdev, ring, &ib, NULL, 16);
> -	if (r) {
> -		ttm_eu_backoff_reservation(&head);
> -		return r;
> -	}
> +	if (r)
> +		goto err;
>  
>  	addr = radeon_bo_gpu_offset(bo);
>  	ib.ptr[0] = PACKET0(UVD_GPCOM_VCPU_DATA0, 0);
> @@ -584,11 +581,9 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
>  	ib.length_dw = 16;
>  
>  	r = radeon_ib_schedule(rdev, &ib, NULL);
> -	if (r) {
> -		ttm_eu_backoff_reservation(&head);
> -		return r;
> -	}
> -	ttm_eu_fence_buffer_objects(&head, ib.fence);
> +	if (r)
> +		goto err;
> +	ttm_eu_fence_buffer_objects(&ticket, &head, ib.fence);
>  
>  	if (fence)
>  		*fence = radeon_fence_ref(ib.fence);
> @@ -596,6 +591,10 @@ static int radeon_uvd_send_msg(struct radeon_device *rdev,
>  	radeon_ib_free(rdev, &ib);
>  	radeon_bo_unref(&bo);
>  	return 0;
> +
> +err:
> +	ttm_eu_backoff_reservation(&ticket, &head);
> +	return r;
>  }
>  
>  /* multiple fence commands without any stream commands in between can
> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
> index 9b07b7d..b912375 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
> @@ -215,7 +215,8 @@ int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
>  
>  int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
>  			  bool interruptible,
> -			  bool no_wait, bool use_sequence, uint32_t sequence)
> +			  bool no_wait, bool use_ticket,
> +			  struct ww_acquire_ctx *ticket)
>  {
>  	int ret;
>  
> @@ -223,17 +224,17 @@ int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
>  		/**
>  		 * Deadlock avoidance for multi-bo reserving.
>  		 */
> -		if (use_sequence && bo->seq_valid) {
> +		if (use_ticket && bo->seq_valid) {
>  			/**
>  			 * We've already reserved this one.
>  			 */
> -			if (unlikely(sequence == bo->val_seq))
> +			if (unlikely(ticket->stamp == bo->val_seq))
>  				return -EDEADLK;
>  			/**
>  			 * Already reserved by a thread that will not back
>  			 * off for us. We need to back off.
>  			 */
> -			if (unlikely(sequence - bo->val_seq < (1 << 31)))
> +			if (unlikely(ticket->stamp - bo->val_seq <= LONG_MAX))
>  				return -EAGAIN;
>  		}
>  
> @@ -246,13 +247,14 @@ int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
>  			return ret;
>  	}
>  
> -	if (use_sequence) {
> +	if (use_ticket) {
>  		bool wake_up = false;
> +
>  		/**
>  		 * Wake up waiters that may need to recheck for deadlock,
>  		 * if we decreased the sequence number.
>  		 */
> -		if (unlikely((bo->val_seq - sequence < (1 << 31))
> +		if (unlikely((bo->val_seq - ticket->stamp <= LONG_MAX)
>  			     || !bo->seq_valid))
>  			wake_up = true;
>  
> @@ -266,7 +268,7 @@ int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
>  		 * written before val_seq was, and just means some slightly
>  		 * increased cpu usage
>  		 */
> -		bo->val_seq = sequence;
> +		bo->val_seq = ticket->stamp;
>  		bo->seq_valid = true;
>  		if (wake_up)
>  			wake_up_all(&bo->event_queue);
> @@ -292,14 +294,15 @@ void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count,
>  
>  int ttm_bo_reserve(struct ttm_buffer_object *bo,
>  		   bool interruptible,
> -		   bool no_wait, bool use_sequence, uint32_t sequence)
> +		   bool no_wait, bool use_ticket,
> +		   struct ww_acquire_ctx *ticket)
>  {
>  	struct ttm_bo_global *glob = bo->glob;
>  	int put_count = 0;
>  	int ret;
>  
> -	ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_sequence,
> -				   sequence);
> +	ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_ticket,
> +				    ticket);
>  	if (likely(ret == 0)) {
>  		spin_lock(&glob->lru_lock);
>  		put_count = ttm_bo_del_from_lru(bo);
> @@ -311,13 +314,14 @@ int ttm_bo_reserve(struct ttm_buffer_object *bo,
>  }
>  
>  int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
> -				  bool interruptible, uint32_t sequence)
> +				  bool interruptible,
> +				  struct ww_acquire_ctx *ticket)
>  {
>  	bool wake_up = false;
>  	int ret;
>  
>  	while (unlikely(atomic_xchg(&bo->reserved, 1) != 0)) {
> -		WARN_ON(bo->seq_valid && sequence == bo->val_seq);
> +		WARN_ON(bo->seq_valid && ticket->stamp == bo->val_seq);
>  
>  		ret = ttm_bo_wait_unreserved(bo, interruptible);
>  
> @@ -325,14 +329,14 @@ int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
>  			return ret;
>  	}
>  
> -	if ((bo->val_seq - sequence < (1 << 31)) || !bo->seq_valid)
> +	if (bo->val_seq - ticket->stamp < LONG_MAX || !bo->seq_valid)
>  		wake_up = true;
>  
>  	/**
>  	 * Wake up waiters that may need to recheck for deadlock,
>  	 * if we decreased the sequence number.
>  	 */
> -	bo->val_seq = sequence;
> +	bo->val_seq = ticket->stamp;
>  	bo->seq_valid = true;
>  	if (wake_up)
>  		wake_up_all(&bo->event_queue);
> @@ -341,12 +345,12 @@ int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
>  }
>  
>  int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
> -			    bool interruptible, uint32_t sequence)
> +			    bool interruptible, struct ww_acquire_ctx *ticket)
>  {
>  	struct ttm_bo_global *glob = bo->glob;
>  	int put_count, ret;
>  
> -	ret = ttm_bo_reserve_slowpath_nolru(bo, interruptible, sequence);
> +	ret = ttm_bo_reserve_slowpath_nolru(bo, interruptible, ticket);
>  	if (likely(!ret)) {
>  		spin_lock(&glob->lru_lock);
>  		put_count = ttm_bo_del_from_lru(bo);
> @@ -357,7 +361,7 @@ int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
>  }
>  EXPORT_SYMBOL(ttm_bo_reserve_slowpath);
>  
> -void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo)
> +void ttm_bo_unreserve_ticket_locked(struct ttm_buffer_object *bo, struct ww_acquire_ctx *ticket)
>  {
>  	ttm_bo_add_to_lru(bo);
>  	atomic_set(&bo->reserved, 0);
> @@ -369,11 +373,21 @@ void ttm_bo_unreserve(struct ttm_buffer_object *bo)
>  	struct ttm_bo_global *glob = bo->glob;
>  
>  	spin_lock(&glob->lru_lock);
> -	ttm_bo_unreserve_locked(bo);
> +	ttm_bo_unreserve_ticket_locked(bo, NULL);
>  	spin_unlock(&glob->lru_lock);
>  }
>  EXPORT_SYMBOL(ttm_bo_unreserve);
>  
> +void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo, struct ww_acquire_ctx *ticket)
> +{
> +	struct ttm_bo_global *glob = bo->glob;
> +
> +	spin_lock(&glob->lru_lock);
> +	ttm_bo_unreserve_ticket_locked(bo, ticket);
> +	spin_unlock(&glob->lru_lock);
> +}
> +EXPORT_SYMBOL(ttm_bo_unreserve_ticket);
> +
>  /*
>   * Call bo->mutex locked.
>   */
> diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
> index 7b90def..efcb734 100644
> --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
> +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
> @@ -32,7 +32,8 @@
>  #include <linux/sched.h>
>  #include <linux/module.h>
>  
> -static void ttm_eu_backoff_reservation_locked(struct list_head *list)
> +static void ttm_eu_backoff_reservation_locked(struct list_head *list,
> +					      struct ww_acquire_ctx *ticket)
>  {
>  	struct ttm_validate_buffer *entry;
>  
> @@ -41,14 +42,15 @@ static void ttm_eu_backoff_reservation_locked(struct list_head *list)
>  		if (!entry->reserved)
>  			continue;
>  
> +		entry->reserved = false;
>  		if (entry->removed) {
> -			ttm_bo_add_to_lru(bo);
> +			ttm_bo_unreserve_ticket_locked(bo, ticket);
>  			entry->removed = false;
>  
> +		} else {
> +			atomic_set(&bo->reserved, 0);
> +			wake_up_all(&bo->event_queue);
>  		}
> -		entry->reserved = false;
> -		atomic_set(&bo->reserved, 0);
> -		wake_up_all(&bo->event_queue);
>  	}
>  }
>  
> @@ -82,7 +84,8 @@ static void ttm_eu_list_ref_sub(struct list_head *list)
>  	}
>  }
>  
> -void ttm_eu_backoff_reservation(struct list_head *list)
> +void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
> +				struct list_head *list)
>  {
>  	struct ttm_validate_buffer *entry;
>  	struct ttm_bo_global *glob;
> @@ -93,7 +96,8 @@ void ttm_eu_backoff_reservation(struct list_head *list)
>  	entry = list_first_entry(list, struct ttm_validate_buffer, head);
>  	glob = entry->bo->glob;
>  	spin_lock(&glob->lru_lock);
> -	ttm_eu_backoff_reservation_locked(list);
> +	ttm_eu_backoff_reservation_locked(list, ticket);
> +	ww_acquire_fini(ticket);
>  	spin_unlock(&glob->lru_lock);
>  }
>  EXPORT_SYMBOL(ttm_eu_backoff_reservation);
> @@ -110,12 +114,12 @@ EXPORT_SYMBOL(ttm_eu_backoff_reservation);
>   * buffers in different orders.
>   */
>  
> -int ttm_eu_reserve_buffers(struct list_head *list)
> +int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
> +			   struct list_head *list)
>  {
>  	struct ttm_bo_global *glob;
>  	struct ttm_validate_buffer *entry;
>  	int ret;
> -	uint32_t val_seq;
>  
>  	if (list_empty(list))
>  		return 0;
> @@ -129,8 +133,8 @@ int ttm_eu_reserve_buffers(struct list_head *list)
>  	entry = list_first_entry(list, struct ttm_validate_buffer, head);
>  	glob = entry->bo->glob;
>  
> +	ww_acquire_init(ticket, &reservation_ww_class);
>  	spin_lock(&glob->lru_lock);
> -	val_seq = entry->bo->bdev->val_seq++;
>  
>  retry:
>  	list_for_each_entry(entry, list, head) {
> @@ -140,7 +144,7 @@ retry:
>  		if (entry->reserved)
>  			continue;
>  
> -		ret = ttm_bo_reserve_nolru(bo, true, true, true, val_seq);
> +		ret = ttm_bo_reserve_nolru(bo, true, true, true, ticket);
>  		switch (ret) {
>  		case 0:
>  			break;
> @@ -148,8 +152,9 @@ retry:
>  			ttm_eu_del_from_lru_locked(list);
>  			spin_unlock(&glob->lru_lock);
>  			ret = ttm_bo_reserve_nolru(bo, true, false,
> -						   true, val_seq);
> +						   true, ticket);
>  			spin_lock(&glob->lru_lock);
> +
>  			if (!ret)
>  				break;
>  
> @@ -158,21 +163,13 @@ retry:
>  
>  			/* fallthrough */
>  		case -EAGAIN:
> -			ttm_eu_backoff_reservation_locked(list);
> -
> -			/*
> -			 * temporarily increase sequence number every retry,
> -			 * to prevent us from seeing our old reservation
> -			 * sequence when someone else reserved the buffer,
> -			 * but hasn't updated the seq_valid/seqno members yet.
> -			 */
> -			val_seq = entry->bo->bdev->val_seq++;
> -
> +			ttm_eu_backoff_reservation_locked(list, ticket);
>  			spin_unlock(&glob->lru_lock);
>  			ttm_eu_list_ref_sub(list);
> -			ret = ttm_bo_reserve_slowpath_nolru(bo, true, val_seq);
> +			ret = ttm_bo_reserve_slowpath_nolru(bo, true, ticket);
>  			if (unlikely(ret != 0))
> -				return ret;
> +				goto err_fini;
> +
>  			spin_lock(&glob->lru_lock);
>  			entry->reserved = true;
>  			if (unlikely(atomic_read(&bo->cpu_writers) > 0)) {
> @@ -191,21 +188,25 @@ retry:
>  		}
>  	}
>  
> +	ww_acquire_done(ticket);
>  	ttm_eu_del_from_lru_locked(list);
>  	spin_unlock(&glob->lru_lock);
>  	ttm_eu_list_ref_sub(list);
> -
>  	return 0;
>  
>  err:
> -	ttm_eu_backoff_reservation_locked(list);
> +	ttm_eu_backoff_reservation_locked(list, ticket);
>  	spin_unlock(&glob->lru_lock);
>  	ttm_eu_list_ref_sub(list);
> +err_fini:
> +	ww_acquire_done(ticket);
> +	ww_acquire_fini(ticket);
>  	return ret;
>  }
>  EXPORT_SYMBOL(ttm_eu_reserve_buffers);
>  
> -void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
> +void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
> +				 struct list_head *list, void *sync_obj)
>  {
>  	struct ttm_validate_buffer *entry;
>  	struct ttm_buffer_object *bo;
> @@ -228,11 +229,12 @@ void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
>  		bo = entry->bo;
>  		entry->old_sync_obj = bo->sync_obj;
>  		bo->sync_obj = driver->sync_obj_ref(sync_obj);
> -		ttm_bo_unreserve_locked(bo);
> +		ttm_bo_unreserve_ticket_locked(bo, ticket);
>  		entry->reserved = false;
>  	}
>  	spin_unlock(&bdev->fence_lock);
>  	spin_unlock(&glob->lru_lock);
> +	ww_acquire_fini(ticket);
>  
>  	list_for_each_entry(entry, list, head) {
>  		if (entry->old_sync_obj)
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> index 394e647..599f646 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
> @@ -1432,6 +1432,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
>  	struct vmw_fence_obj *fence = NULL;
>  	struct vmw_resource *error_resource;
>  	struct list_head resource_list;
> +	struct ww_acquire_ctx ticket;
>  	uint32_t handle;
>  	void *cmd;
>  	int ret;
> @@ -1488,7 +1489,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
>  	if (unlikely(ret != 0))
>  		goto out_err;
>  
> -	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
> +	ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes);
>  	if (unlikely(ret != 0))
>  		goto out_err;
>  
> @@ -1537,7 +1538,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
>  		DRM_ERROR("Fence submission error. Syncing.\n");
>  
>  	vmw_resource_list_unreserve(&sw_context->resource_list, false);
> -	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
> +	ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
>  				    (void *) fence);
>  
>  	if (unlikely(dev_priv->pinned_bo != NULL &&
> @@ -1570,7 +1571,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
>  out_err:
>  	vmw_resource_relocations_free(&sw_context->res_relocations);
>  	vmw_free_relocations(sw_context);
> -	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
> +	ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes);
>  	vmw_resource_list_unreserve(&sw_context->resource_list, true);
>  	vmw_clear_validations(sw_context);
>  	if (unlikely(dev_priv->pinned_bo != NULL &&
> @@ -1644,6 +1645,7 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
>  	struct list_head validate_list;
>  	struct ttm_validate_buffer pinned_val, query_val;
>  	struct vmw_fence_obj *lfence = NULL;
> +	struct ww_acquire_ctx ticket;
>  
>  	if (dev_priv->pinned_bo == NULL)
>  		goto out_unlock;
> @@ -1657,7 +1659,7 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
>  	list_add_tail(&query_val.head, &validate_list);
>  
>  	do {
> -		ret = ttm_eu_reserve_buffers(&validate_list);
> +		ret = ttm_eu_reserve_buffers(&ticket, &validate_list);
>  	} while (ret == -ERESTARTSYS);
>  
>  	if (unlikely(ret != 0)) {
> @@ -1684,7 +1686,7 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
>  						  NULL);
>  		fence = lfence;
>  	}
> -	ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
> +	ttm_eu_fence_buffer_objects(&ticket, &validate_list, (void *) fence);
>  	if (lfence != NULL)
>  		vmw_fence_obj_unreference(&lfence);
>  
> @@ -1696,7 +1698,7 @@ out_unlock:
>  	return;
>  
>  out_no_emit:
> -	ttm_eu_backoff_reservation(&validate_list);
> +	ttm_eu_backoff_reservation(&ticket, &validate_list);
>  out_no_reserve:
>  	ttm_bo_unref(&query_val.bo);
>  	ttm_bo_unref(&pinned_val.bo);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
> index bc78425..ced7946 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
> @@ -990,9 +990,11 @@ void vmw_resource_unreserve(struct vmw_resource *res,
>   * @val_buf:        On successful return contains data about the
>   *                  reserved and validated backup buffer.
>   */
> -int vmw_resource_check_buffer(struct vmw_resource *res,
> -			      bool interruptible,
> -			      struct ttm_validate_buffer *val_buf)
> +static int
> +vmw_resource_check_buffer(struct vmw_resource *res,
> +			  struct ww_acquire_ctx *ticket,
> +			  bool interruptible,
> +			  struct ttm_validate_buffer *val_buf)
>  {
>  	struct list_head val_list;
>  	bool backup_dirty = false;
> @@ -1007,7 +1009,7 @@ int vmw_resource_check_buffer(struct vmw_resource *res,
>  	INIT_LIST_HEAD(&val_list);
>  	val_buf->bo = ttm_bo_reference(&res->backup->base);
>  	list_add_tail(&val_buf->head, &val_list);
> -	ret = ttm_eu_reserve_buffers(&val_list);
> +	ret = ttm_eu_reserve_buffers(ticket, &val_list);
>  	if (unlikely(ret != 0))
>  		goto out_no_reserve;
>  
> @@ -1025,7 +1027,7 @@ int vmw_resource_check_buffer(struct vmw_resource *res,
>  	return 0;
>  
>  out_no_validate:
> -	ttm_eu_backoff_reservation(&val_list);
> +	ttm_eu_backoff_reservation(ticket, &val_list);
>  out_no_reserve:
>  	ttm_bo_unref(&val_buf->bo);
>  	if (backup_dirty)
> @@ -1069,7 +1071,9 @@ int vmw_resource_reserve(struct vmw_resource *res, bool no_backup)
>   *.
>   * @val_buf:        Backup buffer information.
>   */
> -void vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
> +static void
> +vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket,
> +				 struct ttm_validate_buffer *val_buf)
>  {
>  	struct list_head val_list;
>  
> @@ -1078,7 +1082,7 @@ void vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
>  
>  	INIT_LIST_HEAD(&val_list);
>  	list_add_tail(&val_buf->head, &val_list);
> -	ttm_eu_backoff_reservation(&val_list);
> +	ttm_eu_backoff_reservation(ticket, &val_list);
>  	ttm_bo_unref(&val_buf->bo);
>  }
>  
> @@ -1092,12 +1096,13 @@ int vmw_resource_do_evict(struct vmw_resource *res)
>  {
>  	struct ttm_validate_buffer val_buf;
>  	const struct vmw_res_func *func = res->func;
> +	struct ww_acquire_ctx ticket;
>  	int ret;
>  
>  	BUG_ON(!func->may_evict);
>  
>  	val_buf.bo = NULL;
> -	ret = vmw_resource_check_buffer(res, true, &val_buf);
> +	ret = vmw_resource_check_buffer(res, &ticket, true, &val_buf);
>  	if (unlikely(ret != 0))
>  		return ret;
>  
> @@ -1112,7 +1117,7 @@ int vmw_resource_do_evict(struct vmw_resource *res)
>  	res->backup_dirty = true;
>  	res->res_dirty = false;
>  out_no_unbind:
> -	vmw_resource_backoff_reservation(&val_buf);
> +	vmw_resource_backoff_reservation(&ticket, &val_buf);
>  
>  	return ret;
>  }
> diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
> index 3cb5d84..0a992b0 100644
> --- a/include/drm/ttm/ttm_bo_api.h
> +++ b/include/drm/ttm/ttm_bo_api.h
> @@ -234,7 +234,7 @@ struct ttm_buffer_object {
>  	struct list_head ddestroy;
>  	struct list_head swap;
>  	struct list_head io_reserve_lru;
> -	uint32_t val_seq;
> +	unsigned long val_seq;
>  	bool seq_valid;
>  
>  	/**
> diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
> index 9c8dca7..ec18c5f 100644
> --- a/include/drm/ttm/ttm_bo_driver.h
> +++ b/include/drm/ttm/ttm_bo_driver.h
> @@ -38,6 +38,7 @@
>  #include <linux/workqueue.h>
>  #include <linux/fs.h>
>  #include <linux/spinlock.h>
> +#include <linux/reservation.h>
>  
>  struct ttm_backend_func {
>  	/**
> @@ -778,7 +779,7 @@ extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
>   * @bo: A pointer to a struct ttm_buffer_object.
>   * @interruptible: Sleep interruptible if waiting.
>   * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY.
> - * @use_sequence: If @bo is already reserved, Only sleep waiting for
> + * @use_ticket: If @bo is already reserved, Only sleep waiting for
>   * it to become unreserved if @sequence < (@bo)->sequence.
>   *
>   * Locks a buffer object for validation. (Or prevents other processes from
> @@ -819,7 +820,8 @@ extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
>   */
>  extern int ttm_bo_reserve(struct ttm_buffer_object *bo,
>  			  bool interruptible,
> -			  bool no_wait, bool use_sequence, uint32_t sequence);
> +			  bool no_wait, bool use_ticket,
> +			  struct ww_acquire_ctx *ticket);
>  
>  /**
>   * ttm_bo_reserve_slowpath_nolru:
> @@ -836,7 +838,7 @@ extern int ttm_bo_reserve(struct ttm_buffer_object *bo,
>   */
>  extern int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
>  					 bool interruptible,
> -					 uint32_t sequence);
> +					 struct ww_acquire_ctx *ticket);
>  
>  
>  /**
> @@ -850,7 +852,8 @@ extern int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
>   * held by us, this function cannot deadlock any more.
>   */
>  extern int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
> -				   bool interruptible, uint32_t sequence);
> +				   bool interruptible,
> +				   struct ww_acquire_ctx *ticket);
>  
>  /**
>   * ttm_bo_reserve_nolru:
> @@ -876,8 +879,8 @@ extern int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
>   */
>  extern int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
>  				 bool interruptible,
> -				 bool no_wait, bool use_sequence,
> -				 uint32_t sequence);
> +				 bool no_wait, bool use_ticket,
> +				 struct ww_acquire_ctx *ticket);
>  
>  /**
>   * ttm_bo_unreserve
> @@ -889,14 +892,25 @@ extern int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
>  extern void ttm_bo_unreserve(struct ttm_buffer_object *bo);
>  
>  /**
> - * ttm_bo_unreserve_locked
> + * ttm_bo_unreserve_ticket
> + * @bo: A pointer to a struct ttm_buffer_object.
> + * @ticket: ww_acquire_ctx used for reserving
>   *
> + * Unreserve a previous reservation of @bo made with @ticket.
> + */
> +extern void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo,
> +				    struct ww_acquire_ctx *ticket);
> +
> +/**
> + * ttm_bo_unreserve_locked
>   * @bo: A pointer to a struct ttm_buffer_object.
> + * @ticket: ww_acquire_ctx used for reserving, or NULL
>   *
> - * Unreserve a previous reservation of @bo.
> + * Unreserve a previous reservation of @bo made with @ticket.
>   * Needs to be called with struct ttm_bo_global::lru_lock held.
>   */
> -extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo);
> +extern void ttm_bo_unreserve_ticket_locked(struct ttm_buffer_object *bo,
> +					   struct ww_acquire_ctx *ticket);
>  
>  /*
>   * ttm_bo_util.c
> diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h
> index 547e19f..ba71ef9 100644
> --- a/include/drm/ttm/ttm_execbuf_util.h
> +++ b/include/drm/ttm/ttm_execbuf_util.h
> @@ -33,6 +33,7 @@
>  
>  #include <ttm/ttm_bo_api.h>
>  #include <linux/list.h>
> +#include <linux/reservation.h>
>  
>  /**
>   * struct ttm_validate_buffer
> @@ -57,17 +58,20 @@ struct ttm_validate_buffer {
>  /**
>   * function ttm_eu_backoff_reservation
>   *
> + * @ticket:   ww_acquire_ctx from reserve call
>   * @list:     thread private list of ttm_validate_buffer structs.
>   *
>   * Undoes all buffer validation reservations for bos pointed to by
>   * the list entries.
>   */
>  
> -extern void ttm_eu_backoff_reservation(struct list_head *list);
> +extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
> +				       struct list_head *list);
>  
>  /**
>   * function ttm_eu_reserve_buffers
>   *
> + * @ticket:  [out] ww_acquire_ctx returned by call.
>   * @list:    thread private list of ttm_validate_buffer structs.
>   *
>   * Tries to reserve bos pointed to by the list entries for validation.
> @@ -90,11 +94,13 @@ extern void ttm_eu_backoff_reservation(struct list_head *list);
>   * has failed.
>   */
>  
> -extern int ttm_eu_reserve_buffers(struct list_head *list);
> +extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
> +				  struct list_head *list);
>  
>  /**
>   * function ttm_eu_fence_buffer_objects.
>   *
> + * @ticket:      ww_acquire_ctx from reserve call
>   * @list:        thread private list of ttm_validate_buffer structs.
>   * @sync_obj:    The new sync object for the buffers.
>   *
> @@ -104,6 +110,7 @@ extern int ttm_eu_reserve_buffers(struct list_head *list);
>   *
>   */
>  
> -extern void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj);
> +extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
> +					struct list_head *list, void *sync_obj);
>  
>  #endif
> -- 
> 1.8.3.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 7054706..e35d468 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -277,10 +277,12 @@  struct validate_op {
 	struct list_head vram_list;
 	struct list_head gart_list;
 	struct list_head both_list;
+	struct ww_acquire_ctx ticket;
 };
 
 static void
-validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
+validate_fini_list(struct list_head *list, struct nouveau_fence *fence,
+		   struct ww_acquire_ctx *ticket)
 {
 	struct list_head *entry, *tmp;
 	struct nouveau_bo *nvbo;
@@ -297,17 +299,24 @@  validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
 
 		list_del(&nvbo->entry);
 		nvbo->reserved_by = NULL;
-		ttm_bo_unreserve(&nvbo->bo);
+		ttm_bo_unreserve_ticket(&nvbo->bo, ticket);
 		drm_gem_object_unreference_unlocked(nvbo->gem);
 	}
 }
 
 static void
-validate_fini(struct validate_op *op, struct nouveau_fence* fence)
+validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence)
 {
-	validate_fini_list(&op->vram_list, fence);
-	validate_fini_list(&op->gart_list, fence);
-	validate_fini_list(&op->both_list, fence);
+	validate_fini_list(&op->vram_list, fence, &op->ticket);
+	validate_fini_list(&op->gart_list, fence, &op->ticket);
+	validate_fini_list(&op->both_list, fence, &op->ticket);
+}
+
+static void
+validate_fini(struct validate_op *op, struct nouveau_fence *fence)
+{
+	validate_fini_no_ticket(op, fence);
+	ww_acquire_fini(&op->ticket);
 }
 
 static int
@@ -317,13 +326,11 @@  validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
 {
 	struct nouveau_cli *cli = nouveau_cli(file_priv);
 	struct drm_device *dev = chan->drm->dev;
-	struct nouveau_drm *drm = nouveau_drm(dev);
-	uint32_t sequence;
 	int trycnt = 0;
 	int ret, i;
 	struct nouveau_bo *res_bo = NULL;
 
-	sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
+	ww_acquire_init(&op->ticket, &reservation_ww_class);
 retry:
 	if (++trycnt > 100000) {
 		NV_ERROR(cli, "%s failed and gave up.\n", __func__);
@@ -338,6 +345,7 @@  retry:
 		gem = drm_gem_object_lookup(dev, file_priv, b->handle);
 		if (!gem) {
 			NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
+			ww_acquire_done(&op->ticket);
 			validate_fini(op, NULL);
 			return -ENOENT;
 		}
@@ -352,21 +360,23 @@  retry:
 			NV_ERROR(cli, "multiple instances of buffer %d on "
 				      "validation list\n", b->handle);
 			drm_gem_object_unreference_unlocked(gem);
+			ww_acquire_done(&op->ticket);
 			validate_fini(op, NULL);
 			return -EINVAL;
 		}
 
-		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence);
+		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, &op->ticket);
 		if (ret) {
-			validate_fini(op, NULL);
+			validate_fini_no_ticket(op, NULL);
 			if (unlikely(ret == -EAGAIN)) {
-				sequence = atomic_add_return(1, &drm->ttm.validate_sequence);
 				ret = ttm_bo_reserve_slowpath(&nvbo->bo, true,
-							      sequence);
+							      &op->ticket);
 				if (!ret)
 					res_bo = nvbo;
 			}
 			if (unlikely(ret)) {
+				ww_acquire_done(&op->ticket);
+				ww_acquire_fini(&op->ticket);
 				drm_gem_object_unreference_unlocked(gem);
 				if (ret != -ERESTARTSYS)
 					NV_ERROR(cli, "fail reserve\n");
@@ -390,6 +400,7 @@  retry:
 			NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
 				 b->valid_domains);
 			list_add_tail(&nvbo->entry, &op->both_list);
+			ww_acquire_done(&op->ticket);
 			validate_fini(op, NULL);
 			return -EINVAL;
 		}
@@ -397,6 +408,7 @@  retry:
 			goto retry;
 	}
 
+	ww_acquire_done(&op->ticket);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 142ce6c..eaf4ff5 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -883,6 +883,7 @@  struct radeon_cs_parser {
 	u32			cs_flags;
 	u32			ring;
 	s32			priority;
+	struct ww_acquire_ctx	ticket;
 };
 
 extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 7e265a5..8a91901 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -106,7 +106,7 @@  static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 		radeon_bo_list_add_object(&p->relocs[i].lobj,
 					  &p->validated);
 	}
-	return radeon_bo_list_validate(&p->validated, p->ring);
+	return radeon_bo_list_validate(&p->ticket, &p->validated, p->ring);
 }
 
 static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority)
@@ -314,15 +314,17 @@  int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
  * If error is set than unvalidate buffer, otherwise just free memory
  * used by parsing context.
  **/
-static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
+static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bool backoff)
 {
 	unsigned i;
 
 	if (!error) {
-		ttm_eu_fence_buffer_objects(&parser->validated,
+		ttm_eu_fence_buffer_objects(&parser->ticket,
+					    &parser->validated,
 					    parser->ib.fence);
-	} else {
-		ttm_eu_backoff_reservation(&parser->validated);
+	} else if (backoff) {
+		ttm_eu_backoff_reservation(&parser->ticket,
+					   &parser->validated);
 	}
 
 	if (parser->relocs != NULL) {
@@ -535,7 +537,7 @@  int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 	r = radeon_cs_parser_init(&parser, data);
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
-		radeon_cs_parser_fini(&parser, r);
+		radeon_cs_parser_fini(&parser, r, false);
 		up_read(&rdev->exclusive_lock);
 		r = radeon_cs_handle_lockup(rdev, r);
 		return r;
@@ -544,7 +546,7 @@  int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 	if (r) {
 		if (r != -ERESTARTSYS)
 			DRM_ERROR("Failed to parse relocation %d!\n", r);
-		radeon_cs_parser_fini(&parser, r);
+		radeon_cs_parser_fini(&parser, r, false);
 		up_read(&rdev->exclusive_lock);
 		r = radeon_cs_handle_lockup(rdev, r);
 		return r;
@@ -562,7 +564,7 @@  int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 		goto out;
 	}
 out:
-	radeon_cs_parser_fini(&parser, r);
+	radeon_cs_parser_fini(&parser, r, true);
 	up_read(&rdev->exclusive_lock);
 	r = radeon_cs_handle_lockup(rdev, r);
 	return r;
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 07af5a9..71287bb 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -349,14 +349,15 @@  void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
 	}
 }
 
-int radeon_bo_list_validate(struct list_head *head, int ring)
+int radeon_bo_list_validate(struct ww_acquire_ctx *ticket,
+			    struct list_head *head, int ring)
 {
 	struct radeon_bo_list *lobj;
 	struct radeon_bo *bo;
 	u32 domain;
 	int r;
 
-	r = ttm_eu_reserve_buffers(head);
+	r = ttm_eu_reserve_buffers(ticket, head);
 	if (unlikely(r != 0)) {
 		return r;
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index e2cb80a..3e62a3a 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -128,7 +128,8 @@  extern int radeon_bo_init(struct radeon_device *rdev);
 extern void radeon_bo_fini(struct radeon_device *rdev);
 extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
 				struct list_head *head);
-extern int radeon_bo_list_validate(struct list_head *head, int ring);
+extern int radeon_bo_list_validate(struct ww_acquire_ctx *ticket,
+				   struct list_head *head, int ring);
 extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
 				struct vm_area_struct *vma);
 extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index cad735d..0078cdf 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -542,6 +542,7 @@  static int radeon_uvd_send_msg(struct radeon_device *rdev,
 			       struct radeon_fence **fence)
 {
 	struct ttm_validate_buffer tv;
+	struct ww_acquire_ctx ticket;
 	struct list_head head;
 	struct radeon_ib ib;
 	uint64_t addr;
@@ -553,7 +554,7 @@  static int radeon_uvd_send_msg(struct radeon_device *rdev,
 	INIT_LIST_HEAD(&head);
 	list_add(&tv.head, &head);
 
-	r = ttm_eu_reserve_buffers(&head);
+	r = ttm_eu_reserve_buffers(&ticket, &head);
 	if (r)
 		return r;
 
@@ -561,16 +562,12 @@  static int radeon_uvd_send_msg(struct radeon_device *rdev,
 	radeon_uvd_force_into_uvd_segment(bo);
 
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
-	if (r) {
-		ttm_eu_backoff_reservation(&head);
-		return r;
-	}
+	if (r) 
+		goto err;
 
 	r = radeon_ib_get(rdev, ring, &ib, NULL, 16);
-	if (r) {
-		ttm_eu_backoff_reservation(&head);
-		return r;
-	}
+	if (r)
+		goto err;
 
 	addr = radeon_bo_gpu_offset(bo);
 	ib.ptr[0] = PACKET0(UVD_GPCOM_VCPU_DATA0, 0);
@@ -584,11 +581,9 @@  static int radeon_uvd_send_msg(struct radeon_device *rdev,
 	ib.length_dw = 16;
 
 	r = radeon_ib_schedule(rdev, &ib, NULL);
-	if (r) {
-		ttm_eu_backoff_reservation(&head);
-		return r;
-	}
-	ttm_eu_fence_buffer_objects(&head, ib.fence);
+	if (r)
+		goto err;
+	ttm_eu_fence_buffer_objects(&ticket, &head, ib.fence);
 
 	if (fence)
 		*fence = radeon_fence_ref(ib.fence);
@@ -596,6 +591,10 @@  static int radeon_uvd_send_msg(struct radeon_device *rdev,
 	radeon_ib_free(rdev, &ib);
 	radeon_bo_unref(&bo);
 	return 0;
+
+err:
+	ttm_eu_backoff_reservation(&ticket, &head);
+	return r;
 }
 
 /* multiple fence commands without any stream commands in between can
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 9b07b7d..b912375 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -215,7 +215,8 @@  int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
 
 int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
 			  bool interruptible,
-			  bool no_wait, bool use_sequence, uint32_t sequence)
+			  bool no_wait, bool use_ticket,
+			  struct ww_acquire_ctx *ticket)
 {
 	int ret;
 
@@ -223,17 +224,17 @@  int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
 		/**
 		 * Deadlock avoidance for multi-bo reserving.
 		 */
-		if (use_sequence && bo->seq_valid) {
+		if (use_ticket && bo->seq_valid) {
 			/**
 			 * We've already reserved this one.
 			 */
-			if (unlikely(sequence == bo->val_seq))
+			if (unlikely(ticket->stamp == bo->val_seq))
 				return -EDEADLK;
 			/**
 			 * Already reserved by a thread that will not back
 			 * off for us. We need to back off.
 			 */
-			if (unlikely(sequence - bo->val_seq < (1 << 31)))
+			if (unlikely(ticket->stamp - bo->val_seq <= LONG_MAX))
 				return -EAGAIN;
 		}
 
@@ -246,13 +247,14 @@  int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
 			return ret;
 	}
 
-	if (use_sequence) {
+	if (use_ticket) {
 		bool wake_up = false;
+
 		/**
 		 * Wake up waiters that may need to recheck for deadlock,
 		 * if we decreased the sequence number.
 		 */
-		if (unlikely((bo->val_seq - sequence < (1 << 31))
+		if (unlikely((bo->val_seq - ticket->stamp <= LONG_MAX)
 			     || !bo->seq_valid))
 			wake_up = true;
 
@@ -266,7 +268,7 @@  int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
 		 * written before val_seq was, and just means some slightly
 		 * increased cpu usage
 		 */
-		bo->val_seq = sequence;
+		bo->val_seq = ticket->stamp;
 		bo->seq_valid = true;
 		if (wake_up)
 			wake_up_all(&bo->event_queue);
@@ -292,14 +294,15 @@  void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count,
 
 int ttm_bo_reserve(struct ttm_buffer_object *bo,
 		   bool interruptible,
-		   bool no_wait, bool use_sequence, uint32_t sequence)
+		   bool no_wait, bool use_ticket,
+		   struct ww_acquire_ctx *ticket)
 {
 	struct ttm_bo_global *glob = bo->glob;
 	int put_count = 0;
 	int ret;
 
-	ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_sequence,
-				   sequence);
+	ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_ticket,
+				    ticket);
 	if (likely(ret == 0)) {
 		spin_lock(&glob->lru_lock);
 		put_count = ttm_bo_del_from_lru(bo);
@@ -311,13 +314,14 @@  int ttm_bo_reserve(struct ttm_buffer_object *bo,
 }
 
 int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
-				  bool interruptible, uint32_t sequence)
+				  bool interruptible,
+				  struct ww_acquire_ctx *ticket)
 {
 	bool wake_up = false;
 	int ret;
 
 	while (unlikely(atomic_xchg(&bo->reserved, 1) != 0)) {
-		WARN_ON(bo->seq_valid && sequence == bo->val_seq);
+		WARN_ON(bo->seq_valid && ticket->stamp == bo->val_seq);
 
 		ret = ttm_bo_wait_unreserved(bo, interruptible);
 
@@ -325,14 +329,14 @@  int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
 			return ret;
 	}
 
-	if ((bo->val_seq - sequence < (1 << 31)) || !bo->seq_valid)
+	if (bo->val_seq - ticket->stamp < LONG_MAX || !bo->seq_valid)
 		wake_up = true;
 
 	/**
 	 * Wake up waiters that may need to recheck for deadlock,
 	 * if we decreased the sequence number.
 	 */
-	bo->val_seq = sequence;
+	bo->val_seq = ticket->stamp;
 	bo->seq_valid = true;
 	if (wake_up)
 		wake_up_all(&bo->event_queue);
@@ -341,12 +345,12 @@  int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
 }
 
 int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
-			    bool interruptible, uint32_t sequence)
+			    bool interruptible, struct ww_acquire_ctx *ticket)
 {
 	struct ttm_bo_global *glob = bo->glob;
 	int put_count, ret;
 
-	ret = ttm_bo_reserve_slowpath_nolru(bo, interruptible, sequence);
+	ret = ttm_bo_reserve_slowpath_nolru(bo, interruptible, ticket);
 	if (likely(!ret)) {
 		spin_lock(&glob->lru_lock);
 		put_count = ttm_bo_del_from_lru(bo);
@@ -357,7 +361,7 @@  int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
 }
 EXPORT_SYMBOL(ttm_bo_reserve_slowpath);
 
-void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo)
+void ttm_bo_unreserve_ticket_locked(struct ttm_buffer_object *bo, struct ww_acquire_ctx *ticket)
 {
 	ttm_bo_add_to_lru(bo);
 	atomic_set(&bo->reserved, 0);
@@ -369,11 +373,21 @@  void ttm_bo_unreserve(struct ttm_buffer_object *bo)
 	struct ttm_bo_global *glob = bo->glob;
 
 	spin_lock(&glob->lru_lock);
-	ttm_bo_unreserve_locked(bo);
+	ttm_bo_unreserve_ticket_locked(bo, NULL);
 	spin_unlock(&glob->lru_lock);
 }
 EXPORT_SYMBOL(ttm_bo_unreserve);
 
+void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo, struct ww_acquire_ctx *ticket)
+{
+	struct ttm_bo_global *glob = bo->glob;
+
+	spin_lock(&glob->lru_lock);
+	ttm_bo_unreserve_ticket_locked(bo, ticket);
+	spin_unlock(&glob->lru_lock);
+}
+EXPORT_SYMBOL(ttm_bo_unreserve_ticket);
+
 /*
  * Call bo->mutex locked.
  */
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index 7b90def..efcb734 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -32,7 +32,8 @@ 
 #include <linux/sched.h>
 #include <linux/module.h>
 
-static void ttm_eu_backoff_reservation_locked(struct list_head *list)
+static void ttm_eu_backoff_reservation_locked(struct list_head *list,
+					      struct ww_acquire_ctx *ticket)
 {
 	struct ttm_validate_buffer *entry;
 
@@ -41,14 +42,15 @@  static void ttm_eu_backoff_reservation_locked(struct list_head *list)
 		if (!entry->reserved)
 			continue;
 
+		entry->reserved = false;
 		if (entry->removed) {
-			ttm_bo_add_to_lru(bo);
+			ttm_bo_unreserve_ticket_locked(bo, ticket);
 			entry->removed = false;
 
+		} else {
+			atomic_set(&bo->reserved, 0);
+			wake_up_all(&bo->event_queue);
 		}
-		entry->reserved = false;
-		atomic_set(&bo->reserved, 0);
-		wake_up_all(&bo->event_queue);
 	}
 }
 
@@ -82,7 +84,8 @@  static void ttm_eu_list_ref_sub(struct list_head *list)
 	}
 }
 
-void ttm_eu_backoff_reservation(struct list_head *list)
+void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
+				struct list_head *list)
 {
 	struct ttm_validate_buffer *entry;
 	struct ttm_bo_global *glob;
@@ -93,7 +96,8 @@  void ttm_eu_backoff_reservation(struct list_head *list)
 	entry = list_first_entry(list, struct ttm_validate_buffer, head);
 	glob = entry->bo->glob;
 	spin_lock(&glob->lru_lock);
-	ttm_eu_backoff_reservation_locked(list);
+	ttm_eu_backoff_reservation_locked(list, ticket);
+	ww_acquire_fini(ticket);
 	spin_unlock(&glob->lru_lock);
 }
 EXPORT_SYMBOL(ttm_eu_backoff_reservation);
@@ -110,12 +114,12 @@  EXPORT_SYMBOL(ttm_eu_backoff_reservation);
  * buffers in different orders.
  */
 
-int ttm_eu_reserve_buffers(struct list_head *list)
+int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
+			   struct list_head *list)
 {
 	struct ttm_bo_global *glob;
 	struct ttm_validate_buffer *entry;
 	int ret;
-	uint32_t val_seq;
 
 	if (list_empty(list))
 		return 0;
@@ -129,8 +133,8 @@  int ttm_eu_reserve_buffers(struct list_head *list)
 	entry = list_first_entry(list, struct ttm_validate_buffer, head);
 	glob = entry->bo->glob;
 
+	ww_acquire_init(ticket, &reservation_ww_class);
 	spin_lock(&glob->lru_lock);
-	val_seq = entry->bo->bdev->val_seq++;
 
 retry:
 	list_for_each_entry(entry, list, head) {
@@ -140,7 +144,7 @@  retry:
 		if (entry->reserved)
 			continue;
 
-		ret = ttm_bo_reserve_nolru(bo, true, true, true, val_seq);
+		ret = ttm_bo_reserve_nolru(bo, true, true, true, ticket);
 		switch (ret) {
 		case 0:
 			break;
@@ -148,8 +152,9 @@  retry:
 			ttm_eu_del_from_lru_locked(list);
 			spin_unlock(&glob->lru_lock);
 			ret = ttm_bo_reserve_nolru(bo, true, false,
-						   true, val_seq);
+						   true, ticket);
 			spin_lock(&glob->lru_lock);
+
 			if (!ret)
 				break;
 
@@ -158,21 +163,13 @@  retry:
 
 			/* fallthrough */
 		case -EAGAIN:
-			ttm_eu_backoff_reservation_locked(list);
-
-			/*
-			 * temporarily increase sequence number every retry,
-			 * to prevent us from seeing our old reservation
-			 * sequence when someone else reserved the buffer,
-			 * but hasn't updated the seq_valid/seqno members yet.
-			 */
-			val_seq = entry->bo->bdev->val_seq++;
-
+			ttm_eu_backoff_reservation_locked(list, ticket);
 			spin_unlock(&glob->lru_lock);
 			ttm_eu_list_ref_sub(list);
-			ret = ttm_bo_reserve_slowpath_nolru(bo, true, val_seq);
+			ret = ttm_bo_reserve_slowpath_nolru(bo, true, ticket);
 			if (unlikely(ret != 0))
-				return ret;
+				goto err_fini;
+
 			spin_lock(&glob->lru_lock);
 			entry->reserved = true;
 			if (unlikely(atomic_read(&bo->cpu_writers) > 0)) {
@@ -191,21 +188,25 @@  retry:
 		}
 	}
 
+	ww_acquire_done(ticket);
 	ttm_eu_del_from_lru_locked(list);
 	spin_unlock(&glob->lru_lock);
 	ttm_eu_list_ref_sub(list);
-
 	return 0;
 
 err:
-	ttm_eu_backoff_reservation_locked(list);
+	ttm_eu_backoff_reservation_locked(list, ticket);
 	spin_unlock(&glob->lru_lock);
 	ttm_eu_list_ref_sub(list);
+err_fini:
+	ww_acquire_done(ticket);
+	ww_acquire_fini(ticket);
 	return ret;
 }
 EXPORT_SYMBOL(ttm_eu_reserve_buffers);
 
-void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
+void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
+				 struct list_head *list, void *sync_obj)
 {
 	struct ttm_validate_buffer *entry;
 	struct ttm_buffer_object *bo;
@@ -228,11 +229,12 @@  void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj)
 		bo = entry->bo;
 		entry->old_sync_obj = bo->sync_obj;
 		bo->sync_obj = driver->sync_obj_ref(sync_obj);
-		ttm_bo_unreserve_locked(bo);
+		ttm_bo_unreserve_ticket_locked(bo, ticket);
 		entry->reserved = false;
 	}
 	spin_unlock(&bdev->fence_lock);
 	spin_unlock(&glob->lru_lock);
+	ww_acquire_fini(ticket);
 
 	list_for_each_entry(entry, list, head) {
 		if (entry->old_sync_obj)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 394e647..599f646 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1432,6 +1432,7 @@  int vmw_execbuf_process(struct drm_file *file_priv,
 	struct vmw_fence_obj *fence = NULL;
 	struct vmw_resource *error_resource;
 	struct list_head resource_list;
+	struct ww_acquire_ctx ticket;
 	uint32_t handle;
 	void *cmd;
 	int ret;
@@ -1488,7 +1489,7 @@  int vmw_execbuf_process(struct drm_file *file_priv,
 	if (unlikely(ret != 0))
 		goto out_err;
 
-	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
+	ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes);
 	if (unlikely(ret != 0))
 		goto out_err;
 
@@ -1537,7 +1538,7 @@  int vmw_execbuf_process(struct drm_file *file_priv,
 		DRM_ERROR("Fence submission error. Syncing.\n");
 
 	vmw_resource_list_unreserve(&sw_context->resource_list, false);
-	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
+	ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
 				    (void *) fence);
 
 	if (unlikely(dev_priv->pinned_bo != NULL &&
@@ -1570,7 +1571,7 @@  int vmw_execbuf_process(struct drm_file *file_priv,
 out_err:
 	vmw_resource_relocations_free(&sw_context->res_relocations);
 	vmw_free_relocations(sw_context);
-	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
+	ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes);
 	vmw_resource_list_unreserve(&sw_context->resource_list, true);
 	vmw_clear_validations(sw_context);
 	if (unlikely(dev_priv->pinned_bo != NULL &&
@@ -1644,6 +1645,7 @@  void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
 	struct list_head validate_list;
 	struct ttm_validate_buffer pinned_val, query_val;
 	struct vmw_fence_obj *lfence = NULL;
+	struct ww_acquire_ctx ticket;
 
 	if (dev_priv->pinned_bo == NULL)
 		goto out_unlock;
@@ -1657,7 +1659,7 @@  void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
 	list_add_tail(&query_val.head, &validate_list);
 
 	do {
-		ret = ttm_eu_reserve_buffers(&validate_list);
+		ret = ttm_eu_reserve_buffers(&ticket, &validate_list);
 	} while (ret == -ERESTARTSYS);
 
 	if (unlikely(ret != 0)) {
@@ -1684,7 +1686,7 @@  void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
 						  NULL);
 		fence = lfence;
 	}
-	ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
+	ttm_eu_fence_buffer_objects(&ticket, &validate_list, (void *) fence);
 	if (lfence != NULL)
 		vmw_fence_obj_unreference(&lfence);
 
@@ -1696,7 +1698,7 @@  out_unlock:
 	return;
 
 out_no_emit:
-	ttm_eu_backoff_reservation(&validate_list);
+	ttm_eu_backoff_reservation(&ticket, &validate_list);
 out_no_reserve:
 	ttm_bo_unref(&query_val.bo);
 	ttm_bo_unref(&pinned_val.bo);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index bc78425..ced7946 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -990,9 +990,11 @@  void vmw_resource_unreserve(struct vmw_resource *res,
  * @val_buf:        On successful return contains data about the
  *                  reserved and validated backup buffer.
  */
-int vmw_resource_check_buffer(struct vmw_resource *res,
-			      bool interruptible,
-			      struct ttm_validate_buffer *val_buf)
+static int
+vmw_resource_check_buffer(struct vmw_resource *res,
+			  struct ww_acquire_ctx *ticket,
+			  bool interruptible,
+			  struct ttm_validate_buffer *val_buf)
 {
 	struct list_head val_list;
 	bool backup_dirty = false;
@@ -1007,7 +1009,7 @@  int vmw_resource_check_buffer(struct vmw_resource *res,
 	INIT_LIST_HEAD(&val_list);
 	val_buf->bo = ttm_bo_reference(&res->backup->base);
 	list_add_tail(&val_buf->head, &val_list);
-	ret = ttm_eu_reserve_buffers(&val_list);
+	ret = ttm_eu_reserve_buffers(ticket, &val_list);
 	if (unlikely(ret != 0))
 		goto out_no_reserve;
 
@@ -1025,7 +1027,7 @@  int vmw_resource_check_buffer(struct vmw_resource *res,
 	return 0;
 
 out_no_validate:
-	ttm_eu_backoff_reservation(&val_list);
+	ttm_eu_backoff_reservation(ticket, &val_list);
 out_no_reserve:
 	ttm_bo_unref(&val_buf->bo);
 	if (backup_dirty)
@@ -1069,7 +1071,9 @@  int vmw_resource_reserve(struct vmw_resource *res, bool no_backup)
  *.
  * @val_buf:        Backup buffer information.
  */
-void vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
+static void
+vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket,
+				 struct ttm_validate_buffer *val_buf)
 {
 	struct list_head val_list;
 
@@ -1078,7 +1082,7 @@  void vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
 
 	INIT_LIST_HEAD(&val_list);
 	list_add_tail(&val_buf->head, &val_list);
-	ttm_eu_backoff_reservation(&val_list);
+	ttm_eu_backoff_reservation(ticket, &val_list);
 	ttm_bo_unref(&val_buf->bo);
 }
 
@@ -1092,12 +1096,13 @@  int vmw_resource_do_evict(struct vmw_resource *res)
 {
 	struct ttm_validate_buffer val_buf;
 	const struct vmw_res_func *func = res->func;
+	struct ww_acquire_ctx ticket;
 	int ret;
 
 	BUG_ON(!func->may_evict);
 
 	val_buf.bo = NULL;
-	ret = vmw_resource_check_buffer(res, true, &val_buf);
+	ret = vmw_resource_check_buffer(res, &ticket, true, &val_buf);
 	if (unlikely(ret != 0))
 		return ret;
 
@@ -1112,7 +1117,7 @@  int vmw_resource_do_evict(struct vmw_resource *res)
 	res->backup_dirty = true;
 	res->res_dirty = false;
 out_no_unbind:
-	vmw_resource_backoff_reservation(&val_buf);
+	vmw_resource_backoff_reservation(&ticket, &val_buf);
 
 	return ret;
 }
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index 3cb5d84..0a992b0 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -234,7 +234,7 @@  struct ttm_buffer_object {
 	struct list_head ddestroy;
 	struct list_head swap;
 	struct list_head io_reserve_lru;
-	uint32_t val_seq;
+	unsigned long val_seq;
 	bool seq_valid;
 
 	/**
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 9c8dca7..ec18c5f 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -38,6 +38,7 @@ 
 #include <linux/workqueue.h>
 #include <linux/fs.h>
 #include <linux/spinlock.h>
+#include <linux/reservation.h>
 
 struct ttm_backend_func {
 	/**
@@ -778,7 +779,7 @@  extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
  * @bo: A pointer to a struct ttm_buffer_object.
  * @interruptible: Sleep interruptible if waiting.
  * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY.
- * @use_sequence: If @bo is already reserved, Only sleep waiting for
+ * @use_ticket: If @bo is already reserved, Only sleep waiting for
  * it to become unreserved if @sequence < (@bo)->sequence.
  *
  * Locks a buffer object for validation. (Or prevents other processes from
@@ -819,7 +820,8 @@  extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man);
  */
 extern int ttm_bo_reserve(struct ttm_buffer_object *bo,
 			  bool interruptible,
-			  bool no_wait, bool use_sequence, uint32_t sequence);
+			  bool no_wait, bool use_ticket,
+			  struct ww_acquire_ctx *ticket);
 
 /**
  * ttm_bo_reserve_slowpath_nolru:
@@ -836,7 +838,7 @@  extern int ttm_bo_reserve(struct ttm_buffer_object *bo,
  */
 extern int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
 					 bool interruptible,
-					 uint32_t sequence);
+					 struct ww_acquire_ctx *ticket);
 
 
 /**
@@ -850,7 +852,8 @@  extern int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo,
  * held by us, this function cannot deadlock any more.
  */
 extern int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
-				   bool interruptible, uint32_t sequence);
+				   bool interruptible,
+				   struct ww_acquire_ctx *ticket);
 
 /**
  * ttm_bo_reserve_nolru:
@@ -876,8 +879,8 @@  extern int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,
  */
 extern int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
 				 bool interruptible,
-				 bool no_wait, bool use_sequence,
-				 uint32_t sequence);
+				 bool no_wait, bool use_ticket,
+				 struct ww_acquire_ctx *ticket);
 
 /**
  * ttm_bo_unreserve
@@ -889,14 +892,25 @@  extern int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo,
 extern void ttm_bo_unreserve(struct ttm_buffer_object *bo);
 
 /**
- * ttm_bo_unreserve_locked
+ * ttm_bo_unreserve_ticket
+ * @bo: A pointer to a struct ttm_buffer_object.
+ * @ticket: ww_acquire_ctx used for reserving
  *
+ * Unreserve a previous reservation of @bo made with @ticket.
+ */
+extern void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo,
+				    struct ww_acquire_ctx *ticket);
+
+/**
+ * ttm_bo_unreserve_locked
  * @bo: A pointer to a struct ttm_buffer_object.
+ * @ticket: ww_acquire_ctx used for reserving, or NULL
  *
- * Unreserve a previous reservation of @bo.
+ * Unreserve a previous reservation of @bo made with @ticket.
  * Needs to be called with struct ttm_bo_global::lru_lock held.
  */
-extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo);
+extern void ttm_bo_unreserve_ticket_locked(struct ttm_buffer_object *bo,
+					   struct ww_acquire_ctx *ticket);
 
 /*
  * ttm_bo_util.c
diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h
index 547e19f..ba71ef9 100644
--- a/include/drm/ttm/ttm_execbuf_util.h
+++ b/include/drm/ttm/ttm_execbuf_util.h
@@ -33,6 +33,7 @@ 
 
 #include <ttm/ttm_bo_api.h>
 #include <linux/list.h>
+#include <linux/reservation.h>
 
 /**
  * struct ttm_validate_buffer
@@ -57,17 +58,20 @@  struct ttm_validate_buffer {
 /**
  * function ttm_eu_backoff_reservation
  *
+ * @ticket:   ww_acquire_ctx from reserve call
  * @list:     thread private list of ttm_validate_buffer structs.
  *
  * Undoes all buffer validation reservations for bos pointed to by
  * the list entries.
  */
 
-extern void ttm_eu_backoff_reservation(struct list_head *list);
+extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,
+				       struct list_head *list);
 
 /**
  * function ttm_eu_reserve_buffers
  *
+ * @ticket:  [out] ww_acquire_ctx returned by call.
  * @list:    thread private list of ttm_validate_buffer structs.
  *
  * Tries to reserve bos pointed to by the list entries for validation.
@@ -90,11 +94,13 @@  extern void ttm_eu_backoff_reservation(struct list_head *list);
  * has failed.
  */
 
-extern int ttm_eu_reserve_buffers(struct list_head *list);
+extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket,
+				  struct list_head *list);
 
 /**
  * function ttm_eu_fence_buffer_objects.
  *
+ * @ticket:      ww_acquire_ctx from reserve call
  * @list:        thread private list of ttm_validate_buffer structs.
  * @sync_obj:    The new sync object for the buffers.
  *
@@ -104,6 +110,7 @@  extern int ttm_eu_reserve_buffers(struct list_head *list);
  *
  */
 
-extern void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj);
+extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
+					struct list_head *list, void *sync_obj);
 
 #endif