Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecff665f authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Dave Airlie
Browse files

drm/ttm: make ttm reservation calls behave like reservation calls



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: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 786d7257
Loading
Loading
Loading
Loading
+25 −13
Original line number Diff line number Diff line
@@ -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_no_ticket(struct validate_op *op, struct nouveau_fence *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_list(&op->vram_list, fence);
	validate_fini_list(&op->gart_list, fence);
	validate_fini_list(&op->both_list, 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 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
		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 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
			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 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
			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 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
			goto retry;
	}

	ww_acquire_done(&op->ticket);
	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -979,6 +979,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);
+10 −8
Original line number Diff line number Diff line
@@ -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;
@@ -563,7 +565,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;
+3 −2
Original line number Diff line number Diff line
@@ -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;
	}
+2 −1
Original line number Diff line number Diff line
@@ -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,
Loading