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

Commit 40b2dffb authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-4.3' of git://people.freedesktop.org/~agd5f/linux into drm-next

- DP fixes for radeon and amdgpu
- IH ring fix for tonga and fiji
- Lots of GPU scheduler fixes
- Misc additional fixes

* 'drm-next-4.3' of git://people.freedesktop.org/~agd5f/linux: (42 commits)
  drm/amdgpu: fix wait queue handling in the scheduler
  drm/amdgpu: remove extra parameters from scheduler callbacks
  drm/amdgpu: wake up scheduler only when neccessary
  drm/amdgpu: remove entity idle timeout v2
  drm/amdgpu: fix postclose order
  drm/amdgpu: use IB for copy buffer of eviction
  drm/amdgpu: adjust the judgement of removing fence callback
  drm/amdgpu: fix no sync_wait in copy_buffer
  drm/amdgpu: fix last_vm_update fence is not effetive for sched fence
  drm/amdgpu: add priv data to sched
  drm/amdgpu: add owner for sched fence
  drm/amdgpu: remove entity reference from sched fence
  drm/amdgpu: fix and cleanup amd_sched_entity_push_job
  drm/amdgpu: remove amdgpu_bo_list_clone
  drm/amdgpu: remove the context from amdgpu_job
  drm/amdgpu: remove unused parameters to amd_sched_create
  drm/amdgpu: remove sched_lock
  drm/amdgpu: remove prepare_job callback
  drm/amdgpu: cleanup a scheduler function name
  drm/amdgpu: reorder scheduler functions
  ...
parents db561760 c2b6bd7e
Loading
Loading
Loading
Loading
+30 −24
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ struct amdgpu_vm;
struct amdgpu_ring;
struct amdgpu_semaphore;
struct amdgpu_cs_parser;
struct amdgpu_job;
struct amdgpu_irq_src;
struct amdgpu_fpriv;

@@ -246,7 +247,7 @@ struct amdgpu_buffer_funcs {
	unsigned	copy_num_dw;

	/* used for buffer migration */
	void (*emit_copy_buffer)(struct amdgpu_ring *ring,
	void (*emit_copy_buffer)(struct amdgpu_ib *ib,
				 /* src addr in bytes */
				 uint64_t src_offset,
				 /* dst addr in bytes */
@@ -439,9 +440,12 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);

signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
			  struct amdgpu_fence **fences,
			  bool intr, long t);
signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
				       struct fence **array,
				       uint32_t count,
				       bool wait_all,
				       bool intr,
				       signed long t);
struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
void amdgpu_fence_unref(struct amdgpu_fence **fence);

@@ -514,7 +518,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
		       uint64_t dst_offset,
		       uint32_t byte_count,
		       struct reservation_object *resv,
		       struct amdgpu_fence **fence);
		       struct fence **fence);
int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);

struct amdgpu_bo_list_entry {
@@ -650,7 +654,7 @@ struct amdgpu_sa_bo {
	struct amdgpu_sa_manager	*manager;
	unsigned			soffset;
	unsigned			eoffset;
	struct amdgpu_fence		*fence;
	struct fence		        *fence;
};

/*
@@ -692,7 +696,7 @@ bool amdgpu_semaphore_emit_wait(struct amdgpu_ring *ring,
				struct amdgpu_semaphore *semaphore);
void amdgpu_semaphore_free(struct amdgpu_device *adev,
			   struct amdgpu_semaphore **semaphore,
			   struct amdgpu_fence *fence);
			   struct fence *fence);

/*
 * Synchronization
@@ -700,7 +704,8 @@ void amdgpu_semaphore_free(struct amdgpu_device *adev,
struct amdgpu_sync {
	struct amdgpu_semaphore *semaphores[AMDGPU_NUM_SYNCS];
	struct amdgpu_fence	*sync_to[AMDGPU_MAX_RINGS];
	struct amdgpu_fence	*last_vm_update;
	DECLARE_HASHTABLE(fences, 4);
	struct fence	        *last_vm_update;
};

void amdgpu_sync_create(struct amdgpu_sync *sync);
@@ -712,8 +717,9 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
		     void *owner);
int amdgpu_sync_rings(struct amdgpu_sync *sync,
		      struct amdgpu_ring *ring);
int amdgpu_sync_wait(struct amdgpu_sync *sync);
void amdgpu_sync_free(struct amdgpu_device *adev, struct amdgpu_sync *sync,
		      struct amdgpu_fence *fence);
		      struct fence *fence);

/*
 * GART structures, functions & helpers
@@ -871,7 +877,7 @@ int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
					 struct amdgpu_ring *ring,
					 struct amdgpu_ib *ibs,
					 unsigned num_ibs,
					 int (*free_job)(struct amdgpu_cs_parser *),
					 int (*free_job)(struct amdgpu_job *),
					 void *owner,
					 struct fence **fence);

@@ -957,7 +963,7 @@ struct amdgpu_vm_id {
	unsigned		id;
	uint64_t		pd_gpu_addr;
	/* last flushed PD/PT update */
	struct amdgpu_fence	*flushed_updates;
	struct fence	        *flushed_updates;
	/* last use of vmid */
	struct amdgpu_fence	*last_id_use;
};
@@ -1042,7 +1048,7 @@ struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id);
int amdgpu_ctx_put(struct amdgpu_ctx *ctx);

uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring,
			      struct fence *fence, uint64_t queued_seq);
			      struct fence *fence);
struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
				   struct amdgpu_ring *ring, uint64_t seq);

@@ -1077,8 +1083,6 @@ struct amdgpu_bo_list {
	struct amdgpu_bo_list_entry *array;
};

struct amdgpu_bo_list *
amdgpu_bo_list_clone(struct amdgpu_bo_list *list);
struct amdgpu_bo_list *
amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id);
void amdgpu_bo_list_put(struct amdgpu_bo_list *list);
@@ -1255,14 +1259,16 @@ struct amdgpu_cs_parser {

	/* user fence */
	struct amdgpu_user_fence uf;
};

	struct amdgpu_ring *ring;
struct amdgpu_job {
	struct amd_sched_job    base;
	struct amdgpu_device	*adev;
	struct amdgpu_ib	*ibs;
	uint32_t		num_ibs;
	struct mutex            job_lock;
	struct work_struct job_work;
	int (*prepare_job)(struct amdgpu_cs_parser *sched_job);
	int (*run_job)(struct amdgpu_cs_parser *sched_job);
	int (*free_job)(struct amdgpu_cs_parser *sched_job);
	struct amd_sched_fence *s_fence;
	struct amdgpu_user_fence uf;
	int (*free_job)(struct amdgpu_job *sched_job);
};

static inline u32 amdgpu_get_ib_value(struct amdgpu_cs_parser *p, uint32_t ib_idx, int idx)
@@ -2241,7 +2247,7 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
#define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r))
#define amdgpu_display_stop_mc_access(adev, s) (adev)->mode_info.funcs->stop_mc_access((adev), (s))
#define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s))
#define amdgpu_emit_copy_buffer(adev, r, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((r), (s), (d), (b))
#define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib),  (s), (d), (b))
#define amdgpu_emit_fill_buffer(adev, r, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((r), (s), (d), (b))
#define amdgpu_dpm_get_temperature(adev) (adev)->pm.funcs->get_temperature((adev))
#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
@@ -2343,7 +2349,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
		      struct amdgpu_sync *sync);
void amdgpu_vm_flush(struct amdgpu_ring *ring,
		     struct amdgpu_vm *vm,
		     struct amdgpu_fence *updates);
		     struct fence *updates);
void amdgpu_vm_fence(struct amdgpu_device *adev,
		     struct amdgpu_vm *vm,
		     struct amdgpu_fence *fence);
@@ -2373,7 +2379,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
		       uint64_t addr);
void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
		      struct amdgpu_bo_va *bo_va);

int amdgpu_vm_free_job(struct amdgpu_job *job);
/*
 * functions used by amdgpu_encoder.c
 */
+4 −4
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
{
	unsigned long start_jiffies;
	unsigned long end_jiffies;
	struct amdgpu_fence *fence = NULL;
	struct fence *fence = NULL;
	int i, r;

	start_jiffies = jiffies;
@@ -42,17 +42,17 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
		r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence);
		if (r)
			goto exit_do_move;
		r = fence_wait(&fence->base, false);
		r = fence_wait(fence, false);
		if (r)
			goto exit_do_move;
		amdgpu_fence_unref(&fence);
		fence_put(fence);
	}
	end_jiffies = jiffies;
	r = jiffies_to_msecs(end_jiffies - start_jiffies);

exit_do_move:
	if (fence)
		amdgpu_fence_unref(&fence);
		fence_put(fence);
	return r;
}

+0 −33
Original line number Diff line number Diff line
@@ -62,39 +62,6 @@ static int amdgpu_bo_list_create(struct amdgpu_fpriv *fpriv,
	return 0;
}

struct amdgpu_bo_list *
amdgpu_bo_list_clone(struct amdgpu_bo_list *list)
{
	struct amdgpu_bo_list *result;
	unsigned i;

	result = kmalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL);
	if (!result)
		return NULL;

	result->array = drm_calloc_large(list->num_entries,
		sizeof(struct amdgpu_bo_list_entry));
	if (!result->array) {
		kfree(result);
		return NULL;
	}

	mutex_init(&result->lock);
	result->gds_obj = list->gds_obj;
	result->gws_obj = list->gws_obj;
	result->oa_obj = list->oa_obj;
	result->has_userptr = list->has_userptr;
	result->num_entries = list->num_entries;

	memcpy(result->array, list->array, list->num_entries *
	       sizeof(struct amdgpu_bo_list_entry));

	for (i = 0; i < result->num_entries; ++i)
		amdgpu_bo_ref(result->array[i].robj);

	return result;
}

static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id)
{
	struct amdgpu_bo_list *list;
+5 −0
Original line number Diff line number Diff line
@@ -75,6 +75,11 @@ void amdgpu_connector_hotplug(struct drm_connector *connector)
			if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) {
				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
			} else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) {
				/* Don't try to start link training before we
				 * have the dpcd */
				if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
					return;

				/* set it to OFF so that drm_helper_connector_dpms()
				 * won't return immediately since the current state
				 * is ON at this point.
+84 −138
Original line number Diff line number Diff line
@@ -126,19 +126,6 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
	return 0;
}

static void amdgpu_job_work_func(struct work_struct *work)
{
	struct amdgpu_cs_parser *sched_job =
		container_of(work, struct amdgpu_cs_parser,
			     job_work);
	mutex_lock(&sched_job->job_lock);
	if (sched_job->free_job)
		sched_job->free_job(sched_job);
	mutex_unlock(&sched_job->job_lock);
	/* after processing job, free memory */
	fence_put(&sched_job->s_fence->base);
	kfree(sched_job);
}
struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
                                               struct drm_file *filp,
                                               struct amdgpu_ctx *ctx,
@@ -157,10 +144,6 @@ struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
	parser->ctx = ctx;
	parser->ibs = ibs;
	parser->num_ibs = num_ibs;
	if (amdgpu_enable_scheduler) {
		mutex_init(&parser->job_lock);
		INIT_WORK(&parser->job_work, amdgpu_job_work_func);
	}
	for (i = 0; i < num_ibs; i++)
		ibs[i].ctx = ctx;

@@ -173,7 +156,6 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
	uint64_t *chunk_array_user;
	uint64_t *chunk_array = NULL;
	struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
	struct amdgpu_bo_list *bo_list = NULL;
	unsigned size, i;
	int r = 0;

@@ -185,20 +167,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
		r = -EINVAL;
		goto out;
	}
	bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
	if (!amdgpu_enable_scheduler)
		p->bo_list = bo_list;
	else {
		if (bo_list && !bo_list->has_userptr) {
			p->bo_list = amdgpu_bo_list_clone(bo_list);
			amdgpu_bo_list_put(bo_list);
			if (!p->bo_list)
				return -ENOMEM;
		} else if (bo_list && bo_list->has_userptr)
			p->bo_list = bo_list;
		else
			p->bo_list = NULL;
	}
	p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);

	/* get chunks */
	INIT_LIST_HEAD(&p->validated);
@@ -291,7 +260,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
	}


	p->ibs = kmalloc_array(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL);
	p->ibs = kcalloc(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL);
	if (!p->ibs)
		r = -ENOMEM;

@@ -498,24 +467,23 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
	unsigned i;
	if (parser->ctx)
		amdgpu_ctx_put(parser->ctx);
	if (parser->bo_list) {
		if (amdgpu_enable_scheduler && !parser->bo_list->has_userptr)
			amdgpu_bo_list_free(parser->bo_list);
		else
	if (parser->bo_list)
		amdgpu_bo_list_put(parser->bo_list);
	}

	drm_free_large(parser->vm_bos);
	for (i = 0; i < parser->nchunks; i++)
		drm_free_large(parser->chunks[i].kdata);
	kfree(parser->chunks);
	if (!amdgpu_enable_scheduler)
	{
		if (parser->ibs)
			for (i = 0; i < parser->num_ibs; i++)
				amdgpu_ib_free(parser->adev, &parser->ibs[i]);
		kfree(parser->ibs);
		if (parser->uf.bo)
			drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
	}

	if (!amdgpu_enable_scheduler)
	kfree(parser);
}

@@ -533,12 +501,6 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
       amdgpu_cs_parser_fini_late(parser);
}

static int amdgpu_cs_parser_free_job(struct amdgpu_cs_parser *sched_job)
{
       amdgpu_cs_parser_fini_late(sched_job);
       return 0;
}

static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
				   struct amdgpu_vm *vm)
{
@@ -810,68 +772,16 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
	return 0;
}

static int amdgpu_cs_parser_prepare_job(struct amdgpu_cs_parser *sched_job)
{
	int r, i;
	struct amdgpu_cs_parser *parser = sched_job;
	struct amdgpu_device *adev = sched_job->adev;
	bool reserved_buffers = false;

	r = amdgpu_cs_parser_relocs(parser);
	if (r) {
		if (r != -ERESTARTSYS) {
			if (r == -ENOMEM)
				DRM_ERROR("Not enough memory for command submission!\n");
			else
				DRM_ERROR("Failed to process the buffer list %d!\n", r);
		}
	}

	if (!r) {
		reserved_buffers = true;
		r = amdgpu_cs_ib_fill(adev, parser);
	}
	if (!r) {
		r = amdgpu_cs_dependencies(adev, parser);
		if (r)
			DRM_ERROR("Failed in the dependencies handling %d!\n", r);
	}
	if (r) {
		amdgpu_cs_parser_fini(parser, r, reserved_buffers);
		return r;
	}

	for (i = 0; i < parser->num_ibs; i++)
		trace_amdgpu_cs(parser, i);

	r = amdgpu_cs_ib_vm_chunk(adev, parser);
	return r;
}

static struct amdgpu_ring *amdgpu_cs_parser_get_ring(
	struct amdgpu_device *adev,
	struct amdgpu_cs_parser *parser)
static int amdgpu_cs_free_job(struct amdgpu_job *sched_job)
{
	int i, r;

	struct amdgpu_cs_chunk *chunk;
	struct drm_amdgpu_cs_chunk_ib *chunk_ib;
	struct amdgpu_ring *ring;
	for (i = 0; i < parser->nchunks; i++) {
		chunk = &parser->chunks[i];
		chunk_ib = (struct drm_amdgpu_cs_chunk_ib *)chunk->kdata;

		if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB)
			continue;

		r = amdgpu_cs_get_ring(adev, chunk_ib->ip_type,
				       chunk_ib->ip_instance, chunk_ib->ring,
				       &ring);
		if (r)
			return NULL;
		break;
	}
	return ring;
	int i;
	if (sched_job->ibs)
		for (i = 0; i < sched_job->num_ibs; i++)
			amdgpu_ib_free(sched_job->adev, &sched_job->ibs[i]);
	kfree(sched_job->ibs);
	if (sched_job->uf.bo)
		drm_gem_object_unreference_unlocked(&sched_job->uf.bo->gem_base);
	return 0;
}

int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
@@ -879,7 +789,8 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
	struct amdgpu_device *adev = dev->dev_private;
	union drm_amdgpu_cs *cs = data;
	struct amdgpu_cs_parser *parser;
	int r;
	bool reserved_buffers = false;
	int i, r;

	down_read(&adev->exclusive_lock);
	if (!adev->accel_working) {
@@ -899,44 +810,79 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
		return r;
	}

	if (amdgpu_enable_scheduler && parser->num_ibs) {
		struct amdgpu_ring * ring =
			amdgpu_cs_parser_get_ring(adev, parser);
		r = amdgpu_cs_parser_prepare_job(parser);
	r = amdgpu_cs_parser_relocs(parser);
	if (r == -ENOMEM)
		DRM_ERROR("Not enough memory for command submission!\n");
	else if (r && r != -ERESTARTSYS)
		DRM_ERROR("Failed to process the buffer list %d!\n", r);
	else if (!r) {
		reserved_buffers = true;
		r = amdgpu_cs_ib_fill(adev, parser);
	}

	if (!r) {
		r = amdgpu_cs_dependencies(adev, parser);
		if (r)
			DRM_ERROR("Failed in the dependencies handling %d!\n", r);
	}

	if (r)
		goto out;
		parser->ring = ring;
		parser->free_job = amdgpu_cs_parser_free_job;
		mutex_lock(&parser->job_lock);
		r = amd_sched_push_job(ring->scheduler,
				       &parser->ctx->rings[ring->idx].entity,
				       parser,
				       &parser->s_fence);

	for (i = 0; i < parser->num_ibs; i++)
		trace_amdgpu_cs(parser, i);

	r = amdgpu_cs_ib_vm_chunk(adev, parser);
	if (r)
		goto out;

	if (amdgpu_enable_scheduler && parser->num_ibs) {
		struct amdgpu_job *job;
		struct amdgpu_ring * ring =  parser->ibs->ring;
		job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
		if (!job)
			return -ENOMEM;
		job->base.sched = ring->scheduler;
		job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
		job->adev = parser->adev;
		job->ibs = parser->ibs;
		job->num_ibs = parser->num_ibs;
		job->base.owner = parser->filp;
		mutex_init(&job->job_lock);
		if (job->ibs[job->num_ibs - 1].user) {
			memcpy(&job->uf,  &parser->uf,
			       sizeof(struct amdgpu_user_fence));
			job->ibs[job->num_ibs - 1].user = &job->uf;
		}

		job->free_job = amdgpu_cs_free_job;
		mutex_lock(&job->job_lock);
		r = amd_sched_entity_push_job((struct amd_sched_job *)job);
		if (r) {
			mutex_unlock(&parser->job_lock);
			mutex_unlock(&job->job_lock);
			amdgpu_cs_free_job(job);
			kfree(job);
			goto out;
		}
		parser->ibs[parser->num_ibs - 1].sequence =
		cs->out.handle =
			amdgpu_ctx_add_fence(parser->ctx, ring,
					     &parser->s_fence->base,
					     parser->s_fence->v_seq);
		cs->out.handle = parser->s_fence->v_seq;
					     &job->base.s_fence->base);
		parser->ibs[parser->num_ibs - 1].sequence = cs->out.handle;

		list_sort(NULL, &parser->validated, cmp_size_smaller_first);
		ttm_eu_fence_buffer_objects(&parser->ticket,
				&parser->validated,
				&parser->s_fence->base);
				&job->base.s_fence->base);

		mutex_unlock(&parser->job_lock);
		mutex_unlock(&job->job_lock);
		amdgpu_cs_parser_fini_late(parser);
		up_read(&adev->exclusive_lock);
		return 0;
	}
	r = amdgpu_cs_parser_prepare_job(parser);
	if (r)
		goto out;

	cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
out:
	amdgpu_cs_parser_fini(parser, r, true);
	amdgpu_cs_parser_fini(parser, r, reserved_buffers);
	up_read(&adev->exclusive_lock);
	r = amdgpu_cs_handle_lockup(adev, r);
	return r;
Loading