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

Commit 8ed59fd6 authored by Dave Airlie's avatar Dave Airlie
Browse files

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

Radeon and amdgpu fixes for 4.4.  A bit more the usual since I missed
last week.  Misc fixes all over the place.  The big changes are the
tiling configuration fixes for Fiji.

* 'drm-fixes-4.4' of git://people.freedesktop.org/~agd5f/linux: (35 commits)
  drm/amdgpu: reserve/unreserve objects out of map/unmap operations
  drm/amdgpu: move bo_reserve out of amdgpu_vm_clear_bo
  drm/amdgpu: add lock for interval tree in vm
  drm/amdgpu: keep the owner for VMIDs
  drm/amdgpu: move VM manager clean into the VM code again
  drm/amdgpu: cleanup VM coding style
  drm/amdgpu: remove unused VM manager field
  drm/amdgpu: cleanup scheduler command submission
  drm/amdgpu: fix typo in firmware name
  drm/amdgpu: remove the unnecessary parameter adev for amdgpu_sa_bo_new()
  drm/amdgpu: wait interruptible when semaphores are disabled v2
  drm/amdgpu: update pd while updating vm as well
  drm/amdgpu: fix handling order in scheduler CS
  drm/amdgpu: fix incorrect mutex usage v3
  drm/amdgpu: cleanup scheduler fence get/put dance
  drm/amdgpu: add command submission workflow tracepoint
  drm/amdgpu: update Fiji's tiling mode table
  drm/amdgpu: fix bug that can't enter thermal interrupt for bonaire.
  drm/amdgpu: fix seq_printf format string
  drm/radeon: fix quirk for MSI R7 370 Armor 2X
  ...
parents 34258a32 49b02b18
Loading
Loading
Loading
Loading
+58 −62
Original line number Diff line number Diff line
@@ -389,7 +389,6 @@ struct amdgpu_clock {
 * Fences.
 */
struct amdgpu_fence_driver {
	struct amdgpu_ring		*ring;
	uint64_t			gpu_addr;
	volatile uint32_t		*cpu_addr;
	/* sync_seq is protected by ring emission lock */
@@ -398,7 +397,7 @@ struct amdgpu_fence_driver {
	bool				initialized;
	struct amdgpu_irq_src		*irq_src;
	unsigned			irq_type;
	struct delayed_work             lockup_work;
	struct timer_list		fallback_timer;
	wait_queue_head_t		fence_queue;
};

@@ -926,8 +925,6 @@ struct amdgpu_vm_id {
	uint64_t		pd_gpu_addr;
	/* last flushed PD/PT update */
	struct fence	        *flushed_updates;
	/* last use of vmid */
	struct fence		*last_id_use;
};

struct amdgpu_vm {
@@ -957,10 +954,16 @@ struct amdgpu_vm {

	/* for id and flush management per ring */
	struct amdgpu_vm_id	ids[AMDGPU_MAX_RINGS];
	/* for interval tree */
	spinlock_t		it_lock;
};

struct amdgpu_vm_manager {
	struct fence			*active[AMDGPU_NUM_VM];
	struct {
		struct fence	*active;
		atomic_long_t	owner;
	} ids[AMDGPU_NUM_VM];

	uint32_t				max_pfn;
	/* number of VMIDs */
	unsigned				nvm;
@@ -968,13 +971,53 @@ struct amdgpu_vm_manager {
	u64					vram_base_offset;
	/* is vm enabled? */
	bool					enabled;
	/* for hw to save the PD addr on suspend/resume */
	uint32_t			saved_table_addr[AMDGPU_NUM_VM];
	/* vm pte handling */
	const struct amdgpu_vm_pte_funcs        *vm_pte_funcs;
	struct amdgpu_ring                      *vm_pte_funcs_ring;
};

void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
					       struct amdgpu_vm *vm,
					       struct list_head *head);
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 fence *updates);
void amdgpu_vm_fence(struct amdgpu_device *adev,
		     struct amdgpu_vm *vm,
		     struct fence *fence);
uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
				    struct amdgpu_vm *vm);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
			  struct amdgpu_vm *vm);
int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
			     struct amdgpu_sync *sync);
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
			struct amdgpu_bo_va *bo_va,
			struct ttm_mem_reg *mem);
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
			     struct amdgpu_bo *bo);
struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
				       struct amdgpu_bo *bo);
struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
				      struct amdgpu_vm *vm,
				      struct amdgpu_bo *bo);
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
		     struct amdgpu_bo_va *bo_va,
		     uint64_t addr, uint64_t offset,
		     uint64_t size, uint32_t flags);
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
		       struct amdgpu_bo_va *bo_va,
		       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);

/*
 * context related structures
 */
@@ -1211,6 +1254,7 @@ struct amdgpu_cs_parser {
	/* relocations */
	struct amdgpu_bo_list_entry	*vm_bos;
	struct list_head	validated;
	struct fence		*fence;

	struct amdgpu_ib	*ibs;
	uint32_t		num_ibs;
@@ -1226,7 +1270,7 @@ struct amdgpu_job {
	struct amdgpu_device	*adev;
	struct amdgpu_ib	*ibs;
	uint32_t		num_ibs;
	struct mutex            job_lock;
	void			*owner;
	struct amdgpu_user_fence uf;
	int (*free_job)(struct amdgpu_job *job);
};
@@ -2257,11 +2301,6 @@ void amdgpu_pci_config_reset(struct amdgpu_device *adev);
bool amdgpu_card_posted(struct amdgpu_device *adev);
void amdgpu_update_display_priority(struct amdgpu_device *adev);
bool amdgpu_boot_test_post_card(struct amdgpu_device *adev);
struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
						 struct drm_file *filp,
						 struct amdgpu_ctx *ctx,
						 struct amdgpu_ib *ibs,
						 uint32_t num_ibs);

int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
@@ -2318,49 +2357,6 @@ int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
			     unsigned long arg);

/*
 * vm
 */
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
					  struct amdgpu_vm *vm,
					  struct list_head *head);
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 fence *updates);
void amdgpu_vm_fence(struct amdgpu_device *adev,
		     struct amdgpu_vm *vm,
		     struct amdgpu_fence *fence);
uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
				    struct amdgpu_vm *vm);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
				struct amdgpu_vm *vm);
int amdgpu_vm_clear_invalids(struct amdgpu_device *adev,
				struct amdgpu_vm *vm, struct amdgpu_sync *sync);
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
			struct amdgpu_bo_va *bo_va,
			struct ttm_mem_reg *mem);
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
			     struct amdgpu_bo *bo);
struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
				       struct amdgpu_bo *bo);
struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
				      struct amdgpu_vm *vm,
				      struct amdgpu_bo *bo);
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
		     struct amdgpu_bo_va *bo_va,
		     uint64_t addr, uint64_t offset,
		     uint64_t size, uint32_t flags);
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
		       struct amdgpu_bo_va *bo_va,
		       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
 */
+72 −105
Original line number Diff line number Diff line
@@ -127,30 +127,6 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
	return 0;
}

struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
                                               struct drm_file *filp,
                                               struct amdgpu_ctx *ctx,
                                               struct amdgpu_ib *ibs,
                                               uint32_t num_ibs)
{
	struct amdgpu_cs_parser *parser;
	int i;

	parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL);
	if (!parser)
		return NULL;

	parser->adev = adev;
	parser->filp = filp;
	parser->ctx = ctx;
	parser->ibs = ibs;
	parser->num_ibs = num_ibs;
	for (i = 0; i < num_ibs; i++)
		ibs[i].ctx = ctx;

	return parser;
}

int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
{
	union drm_amdgpu_cs *cs = data;
@@ -463,8 +439,18 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,
	return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
}

static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff)
/**
 * cs_parser_fini() - clean parser states
 * @parser:	parser structure holding parsing context.
 * @error:	error number
 *
 * If error is set than unvalidate buffer, otherwise just free memory
 * used by parsing context.
 **/
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
{
	unsigned i;

	if (!error) {
		/* Sort the buffer list from the smallest to largest buffer,
		 * which affects the order of buffers in the LRU list.
@@ -480,16 +466,13 @@ static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int err

		ttm_eu_fence_buffer_objects(&parser->ticket,
					    &parser->validated,
				&parser->ibs[parser->num_ibs-1].fence->base);
					    parser->fence);
	} else if (backoff) {
		ttm_eu_backoff_reservation(&parser->ticket,
					   &parser->validated);
	}
}
	fence_put(parser->fence);

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)
@@ -499,8 +482,6 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
	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]);
@@ -509,23 +490,6 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
		drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
}

	kfree(parser);
}

/**
 * cs_parser_fini() - clean parser states
 * @parser:	parser structure holding parsing context.
 * @error:	error number
 *
 * If error is set than unvalidate buffer, otherwise just free memory
 * used by parsing context.
 **/
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
{
       amdgpu_cs_parser_fini_early(parser, error, backoff);
       amdgpu_cs_parser_fini_late(parser);
}

static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
				   struct amdgpu_vm *vm)
{
@@ -610,15 +574,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
	}

	r = amdgpu_bo_vm_update_pte(parser, vm);
	if (r) {
		goto out;
	}
	if (!r)
		amdgpu_cs_sync_rings(parser);
	if (!amdgpu_enable_scheduler)
		r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs,
				       parser->filp);

out:
	return r;
}

@@ -828,36 +786,36 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
	union drm_amdgpu_cs *cs = data;
	struct amdgpu_fpriv *fpriv = filp->driver_priv;
	struct amdgpu_vm *vm = &fpriv->vm;
	struct amdgpu_cs_parser *parser;
	struct amdgpu_cs_parser parser = {};
	bool reserved_buffers = false;
	int i, r;

	if (!adev->accel_working)
		return -EBUSY;

	parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
	if (!parser)
		return -ENOMEM;
	r = amdgpu_cs_parser_init(parser, data);
	parser.adev = adev;
	parser.filp = filp;

	r = amdgpu_cs_parser_init(&parser, data);
	if (r) {
		DRM_ERROR("Failed to initialize parser !\n");
		amdgpu_cs_parser_fini(parser, r, false);
		amdgpu_cs_parser_fini(&parser, r, false);
		r = amdgpu_cs_handle_lockup(adev, r);
		return r;
	}
	mutex_lock(&vm->mutex);
	r = amdgpu_cs_parser_relocs(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);
		r = amdgpu_cs_ib_fill(adev, &parser);
	}

	if (!r) {
		r = amdgpu_cs_dependencies(adev, parser);
		r = amdgpu_cs_dependencies(adev, &parser);
		if (r)
			DRM_ERROR("Failed in the dependencies handling %d!\n", r);
	}
@@ -865,62 +823,71 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
	if (r)
		goto out;

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

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

	if (amdgpu_enable_scheduler && parser->num_ibs) {
	if (amdgpu_enable_scheduler && parser.num_ibs) {
		struct amdgpu_ring * ring = parser.ibs->ring;
		struct amd_sched_fence *fence;
		struct amdgpu_job *job;
		struct amdgpu_ring * ring =  parser->ibs->ring;

		job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
		if (!job) {
			r = -ENOMEM;
			goto out;
		}

		job->base.sched = &ring->sched;
		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);
		job->base.s_entity = &parser.ctx->rings[ring->idx].entity;
		job->adev = parser.adev;
		job->owner = parser.filp;
		job->free_job = amdgpu_cs_free_job;

		job->ibs = parser.ibs;
		job->num_ibs = parser.num_ibs;
		parser.ibs = NULL;
		parser.num_ibs = 0;

		if (job->ibs[job->num_ibs - 1].user) {
			memcpy(&job->uf,  &parser->uf,
			       sizeof(struct amdgpu_user_fence));
			job->uf = parser.uf;
			job->ibs[job->num_ibs - 1].user = &job->uf;
			parser.uf.bo = NULL;
		}

		job->free_job = amdgpu_cs_free_job;
		mutex_lock(&job->job_lock);
		r = amd_sched_entity_push_job(&job->base);
		if (r) {
			mutex_unlock(&job->job_lock);
		fence = amd_sched_fence_create(job->base.s_entity,
					       parser.filp);
		if (!fence) {
			r = -ENOMEM;
			amdgpu_cs_free_job(job);
			kfree(job);
			goto out;
		}
		cs->out.handle =
			amdgpu_ctx_add_fence(parser->ctx, ring,
					     &job->base.s_fence->base);
		parser->ibs[parser->num_ibs - 1].sequence = cs->out.handle;
		job->base.s_fence = fence;
		parser.fence = fence_get(&fence->base);

		list_sort(NULL, &parser->validated, cmp_size_smaller_first);
		ttm_eu_fence_buffer_objects(&parser->ticket,
				&parser->validated,
				&job->base.s_fence->base);
		cs->out.handle = amdgpu_ctx_add_fence(parser.ctx, ring,
						      &fence->base);
		job->ibs[job->num_ibs - 1].sequence = cs->out.handle;

		mutex_unlock(&job->job_lock);
		amdgpu_cs_parser_fini_late(parser);
		mutex_unlock(&vm->mutex);
		return 0;
		trace_amdgpu_cs_ioctl(job);
		amd_sched_entity_push_job(&job->base);

	} else {
		struct amdgpu_fence *fence;

		r = amdgpu_ib_schedule(adev, parser.num_ibs, parser.ibs,
				       parser.filp);
		fence = parser.ibs[parser.num_ibs - 1].fence;
		parser.fence = fence_get(&fence->base);
		cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;
	}

	cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
out:
	amdgpu_cs_parser_fini(parser, r, reserved_buffers);
	amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
	mutex_unlock(&vm->mutex);
	r = amdgpu_cs_handle_lockup(adev, r);
	return r;
+54 −47
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@
 * that the the relevant GPU caches have been flushed.
 */

static struct kmem_cache *amdgpu_fence_slab;
static atomic_t amdgpu_fence_slab_ref = ATOMIC_INIT(0);

/**
 * amdgpu_fence_write - write a fence value
 *
@@ -84,24 +87,6 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
	return seq;
}

/**
 * amdgpu_fence_schedule_check - schedule lockup check
 *
 * @ring: pointer to struct amdgpu_ring
 *
 * Queues a delayed work item to check for lockups.
 */
static void amdgpu_fence_schedule_check(struct amdgpu_ring *ring)
{
	/*
	 * Do not reset the timer here with mod_delayed_work,
	 * this can livelock in an interaction with TTM delayed destroy.
	 */
	queue_delayed_work(system_power_efficient_wq,
		&ring->fence_drv.lockup_work,
		AMDGPU_FENCE_JIFFIES_TIMEOUT);
}

/**
 * amdgpu_fence_emit - emit a fence on the requested ring
 *
@@ -118,7 +103,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
	struct amdgpu_device *adev = ring->adev;

	/* we are protected by the ring emission mutex */
	*fence = kmalloc(sizeof(struct amdgpu_fence), GFP_KERNEL);
	*fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
	if ((*fence) == NULL) {
		return -ENOMEM;
	}
@@ -132,10 +117,22 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
	amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
			       (*fence)->seq,
			       AMDGPU_FENCE_FLAG_INT);
	trace_amdgpu_fence_emit(ring->adev->ddev, ring->idx, (*fence)->seq);
	return 0;
}

/**
 * amdgpu_fence_schedule_fallback - schedule fallback check
 *
 * @ring: pointer to struct amdgpu_ring
 *
 * Start a timer as fallback to our interrupts.
 */
static void amdgpu_fence_schedule_fallback(struct amdgpu_ring *ring)
{
	mod_timer(&ring->fence_drv.fallback_timer,
		  jiffies + AMDGPU_FENCE_JIFFIES_TIMEOUT);
}

/**
 * amdgpu_fence_activity - check for fence activity
 *
@@ -202,45 +199,38 @@ static bool amdgpu_fence_activity(struct amdgpu_ring *ring)
	} while (atomic64_xchg(&ring->fence_drv.last_seq, seq) > seq);

	if (seq < last_emitted)
		amdgpu_fence_schedule_check(ring);
		amdgpu_fence_schedule_fallback(ring);

	return wake;
}

/**
 * amdgpu_fence_check_lockup - check for hardware lockup
 * amdgpu_fence_process - process a fence
 *
 * @work: delayed work item
 * @adev: amdgpu_device pointer
 * @ring: ring index the fence is associated with
 *
 * Checks for fence activity and if there is none probe
 * the hardware if a lockup occured.
 * Checks the current fence value and wakes the fence queue
 * if the sequence number has increased (all asics).
 */
static void amdgpu_fence_check_lockup(struct work_struct *work)
void amdgpu_fence_process(struct amdgpu_ring *ring)
{
	struct amdgpu_fence_driver *fence_drv;
	struct amdgpu_ring *ring;

	fence_drv = container_of(work, struct amdgpu_fence_driver,
				lockup_work.work);
	ring = fence_drv->ring;

	if (amdgpu_fence_activity(ring))
		wake_up_all(&ring->fence_drv.fence_queue);
}

/**
 * amdgpu_fence_process - process a fence
 * amdgpu_fence_fallback - fallback for hardware interrupts
 *
 * @adev: amdgpu_device pointer
 * @ring: ring index the fence is associated with
 * @work: delayed work item
 *
 * Checks the current fence value and wakes the fence queue
 * if the sequence number has increased (all asics).
 * Checks for fence activity.
 */
void amdgpu_fence_process(struct amdgpu_ring *ring)
static void amdgpu_fence_fallback(unsigned long arg)
{
	if (amdgpu_fence_activity(ring))
		wake_up_all(&ring->fence_drv.fence_queue);
	struct amdgpu_ring *ring = (void *)arg;

	amdgpu_fence_process(ring);
}

/**
@@ -290,7 +280,7 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
	if (atomic64_read(&ring->fence_drv.last_seq) >= seq)
		return 0;

	amdgpu_fence_schedule_check(ring);
	amdgpu_fence_schedule_fallback(ring);
	wait_event(ring->fence_drv.fence_queue, (
		   (signaled = amdgpu_fence_seq_signaled(ring, seq))));

@@ -491,9 +481,8 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
	atomic64_set(&ring->fence_drv.last_seq, 0);
	ring->fence_drv.initialized = false;

	INIT_DELAYED_WORK(&ring->fence_drv.lockup_work,
			amdgpu_fence_check_lockup);
	ring->fence_drv.ring = ring;
	setup_timer(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback,
		    (unsigned long)ring);

	init_waitqueue_head(&ring->fence_drv.fence_queue);

@@ -536,6 +525,13 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
 */
int amdgpu_fence_driver_init(struct amdgpu_device *adev)
{
	if (atomic_inc_return(&amdgpu_fence_slab_ref) == 1) {
		amdgpu_fence_slab = kmem_cache_create(
			"amdgpu_fence", sizeof(struct amdgpu_fence), 0,
			SLAB_HWCACHE_ALIGN, NULL);
		if (!amdgpu_fence_slab)
			return -ENOMEM;
	}
	if (amdgpu_debugfs_fence_init(adev))
		dev_err(adev->dev, "fence debugfs file creation failed\n");

@@ -554,9 +550,12 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
{
	int i, r;

	if (atomic_dec_and_test(&amdgpu_fence_slab_ref))
		kmem_cache_destroy(amdgpu_fence_slab);
	mutex_lock(&adev->ring_lock);
	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
		struct amdgpu_ring *ring = adev->rings[i];

		if (!ring || !ring->fence_drv.initialized)
			continue;
		r = amdgpu_fence_wait_empty(ring);
@@ -568,6 +567,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
		amdgpu_irq_put(adev, ring->fence_drv.irq_src,
			       ring->fence_drv.irq_type);
		amd_sched_fini(&ring->sched);
		del_timer_sync(&ring->fence_drv.fallback_timer);
		ring->fence_drv.initialized = false;
	}
	mutex_unlock(&adev->ring_lock);
@@ -751,18 +751,25 @@ static bool amdgpu_fence_enable_signaling(struct fence *f)
	fence->fence_wake.func = amdgpu_fence_check_signaled;
	__add_wait_queue(&ring->fence_drv.fence_queue, &fence->fence_wake);
	fence_get(f);
	amdgpu_fence_schedule_check(ring);
	if (!timer_pending(&ring->fence_drv.fallback_timer))
		amdgpu_fence_schedule_fallback(ring);
	FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
	return true;
}

static void amdgpu_fence_release(struct fence *f)
{
	struct amdgpu_fence *fence = to_amdgpu_fence(f);
	kmem_cache_free(amdgpu_fence_slab, fence);
}

const struct fence_ops amdgpu_fence_ops = {
	.get_driver_name = amdgpu_fence_get_driver_name,
	.get_timeline_name = amdgpu_fence_get_timeline_name,
	.enable_signaling = amdgpu_fence_enable_signaling,
	.signaled = amdgpu_fence_is_signaled,
	.wait = fence_default_wait,
	.release = NULL,
	.release = amdgpu_fence_release,
};

/*
+21 −3
Original line number Diff line number Diff line
@@ -483,6 +483,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
		if (domain == AMDGPU_GEM_DOMAIN_CPU)
			goto error_unreserve;
	}
	r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
	if (r)
		goto error_unreserve;

	r = amdgpu_vm_clear_freed(adev, bo_va->vm);
	if (r)
@@ -512,6 +515,9 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
	struct amdgpu_fpriv *fpriv = filp->driver_priv;
	struct amdgpu_bo *rbo;
	struct amdgpu_bo_va *bo_va;
	struct ttm_validate_buffer tv, tv_pd;
	struct ww_acquire_ctx ticket;
	struct list_head list, duplicates;
	uint32_t invalid_flags, va_flags = 0;
	int r = 0;

@@ -549,7 +555,18 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
		return -ENOENT;
	mutex_lock(&fpriv->vm.mutex);
	rbo = gem_to_amdgpu_bo(gobj);
	r = amdgpu_bo_reserve(rbo, false);
	INIT_LIST_HEAD(&list);
	INIT_LIST_HEAD(&duplicates);
	tv.bo = &rbo->tbo;
	tv.shared = true;
	list_add(&tv.head, &list);

	if (args->operation == AMDGPU_VA_OP_MAP) {
		tv_pd.bo = &fpriv->vm.page_directory->tbo;
		tv_pd.shared = true;
		list_add(&tv_pd.head, &list);
	}
	r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
	if (r) {
		mutex_unlock(&fpriv->vm.mutex);
		drm_gem_object_unreference_unlocked(gobj);
@@ -558,7 +575,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,

	bo_va = amdgpu_vm_bo_find(&fpriv->vm, rbo);
	if (!bo_va) {
		amdgpu_bo_unreserve(rbo);
		ttm_eu_backoff_reservation(&ticket, &list);
		drm_gem_object_unreference_unlocked(gobj);
		mutex_unlock(&fpriv->vm.mutex);
		return -ENOENT;
	}
@@ -581,7 +599,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
	default:
		break;
	}

	ttm_eu_backoff_reservation(&ticket, &list);
	if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
		amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
	mutex_unlock(&fpriv->vm.mutex);
+2 −2
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ int amdgpu_ib_get(struct amdgpu_ring *ring, struct amdgpu_vm *vm,
	int r;

	if (size) {
		r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
		r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
				      &ib->sa_bo, size, 256);
		if (r) {
			dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
@@ -216,7 +216,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
	}

	if (ib->vm)
		amdgpu_vm_fence(adev, ib->vm, ib->fence);
		amdgpu_vm_fence(adev, ib->vm, &ib->fence->base);

	amdgpu_ring_unlock_commit(ring);
	return 0;
Loading