amdgpu_ctx.c 15.5 KB
Newer Older
A
Alex Deucher 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * Copyright 2015 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: monk liu <monk.liu@amd.com>
 */

25
#include <drm/drm_auth.h>
A
Alex Deucher 已提交
26
#include "amdgpu.h"
27
#include "amdgpu_sched.h"
28
#include "amdgpu_ras.h"
29
#include <linux/nospec.h>
A
Alex Deucher 已提交
30

31 32 33 34 35 36 37 38 39 40 41 42
#define to_amdgpu_ctx_entity(e)	\
	container_of((e), struct amdgpu_ctx_entity, entity)

const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = {
	[AMDGPU_HW_IP_GFX]	=	1,
	[AMDGPU_HW_IP_COMPUTE]	=	4,
	[AMDGPU_HW_IP_DMA]	=	2,
	[AMDGPU_HW_IP_UVD]	=	1,
	[AMDGPU_HW_IP_VCE]	=	1,
	[AMDGPU_HW_IP_UVD_ENC]	=	1,
	[AMDGPU_HW_IP_VCN_DEC]	=	1,
	[AMDGPU_HW_IP_VCN_ENC]	=	1,
43
	[AMDGPU_HW_IP_VCN_JPEG]	=	1,
44 45
};

46
static int amdgpu_ctx_priority_permit(struct drm_file *filp,
47
				      enum drm_sched_priority priority)
48
{
49
	if (priority < 0 || priority >= DRM_SCHED_PRIORITY_COUNT)
50 51
		return -EINVAL;

52
	/* NORMAL and below are accessible by everyone */
53
	if (priority <= DRM_SCHED_PRIORITY_NORMAL)
54 55 56 57 58 59 60 61 62 63 64
		return 0;

	if (capable(CAP_SYS_NICE))
		return 0;

	if (drm_is_current_master(filp))
		return 0;

	return -EACCES;
}

65 66 67
static enum gfx_pipe_priority amdgpu_ctx_sched_prio_to_compute_prio(enum drm_sched_priority prio)
{
	switch (prio) {
68
	case DRM_SCHED_PRIORITY_HIGH:
69 70 71 72 73 74 75
	case DRM_SCHED_PRIORITY_KERNEL:
		return AMDGPU_GFX_PIPE_PRIO_HIGH;
	default:
		return AMDGPU_GFX_PIPE_PRIO_NORMAL;
	}
}

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev,
						 enum drm_sched_priority prio,
						 u32 hw_ip)
{
	unsigned int hw_prio;

	hw_prio = (hw_ip == AMDGPU_HW_IP_COMPUTE) ?
			amdgpu_ctx_sched_prio_to_compute_prio(prio) :
			AMDGPU_RING_PRIO_DEFAULT;
	hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
	if (adev->gpu_sched[hw_ip][hw_prio].num_scheds == 0)
		hw_prio = AMDGPU_RING_PRIO_DEFAULT;

	return hw_prio;
}

static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip,
				   const u32 ring)
A
Alex Deucher 已提交
94
{
95 96 97 98
	struct amdgpu_device *adev = ctx->adev;
	struct amdgpu_ctx_entity *entity;
	struct drm_gpu_scheduler **scheds = NULL, *sched = NULL;
	unsigned num_scheds = 0;
99
	unsigned int hw_prio;
100
	enum drm_sched_priority priority;
101
	int r;
A
Alex Deucher 已提交
102

103 104 105 106
	entity = kcalloc(1, offsetof(typeof(*entity), fences[amdgpu_sched_jobs]),
			 GFP_KERNEL);
	if (!entity)
		return  -ENOMEM;
107

108 109 110
	entity->sequence = 1;
	priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
				ctx->init_priority : ctx->override_priority;
111 112 113 114 115 116 117 118
	hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority, hw_ip);

	hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM);
	scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
	num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;

	if (hw_ip == AMDGPU_HW_IP_VCN_ENC || hw_ip == AMDGPU_HW_IP_VCN_DEC) {
		sched = drm_sched_pick_best(scheds, num_scheds);
119 120
		scheds = &sched;
		num_scheds = 1;
121 122
	}

123 124 125 126 127 128
	r = drm_sched_entity_init(&entity->entity, priority, scheds, num_scheds,
				  &ctx->guilty);
	if (r)
		goto error_free_entity;

	ctx->entities[hw_ip][ring] = entity;
A
Alex Deucher 已提交
129
	return 0;
130

131 132
error_free_entity:
	kfree(entity);
133

134 135
	return r;
}
136

137 138 139 140 141 142
static int amdgpu_ctx_init(struct amdgpu_device *adev,
			   enum drm_sched_priority priority,
			   struct drm_file *filp,
			   struct amdgpu_ctx *ctx)
{
	int r;
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
	r = amdgpu_ctx_priority_permit(filp, priority);
	if (r)
		return r;

	memset(ctx, 0, sizeof(*ctx));

	ctx->adev = adev;

	kref_init(&ctx->refcount);
	spin_lock_init(&ctx->ring_lock);
	mutex_init(&ctx->lock);

	ctx->reset_counter = atomic_read(&adev->gpu_reset_counter);
	ctx->reset_counter_query = ctx->reset_counter;
	ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
	ctx->init_priority = priority;
	ctx->override_priority = DRM_SCHED_PRIORITY_UNSET;

	return 0;
}

static void amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity)
{

	int i;

	if (!entity)
		return;

	for (i = 0; i < amdgpu_sched_jobs; ++i)
		dma_fence_put(entity->fences[i]);

	kfree(entity);
A
Alex Deucher 已提交
177 178
}

179
static void amdgpu_ctx_fini(struct kref *ref)
A
Alex Deucher 已提交
180
{
181
	struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount);
182 183 184
	struct amdgpu_device *adev = ctx->adev;
	unsigned i, j;

185 186 187
	if (!adev)
		return;

188 189 190 191 192
	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
		for (j = 0; j < AMDGPU_MAX_ENTITY_NUM; ++j) {
			amdgpu_ctx_fini_entity(ctx->entities[i][j]);
			ctx->entities[i][j] = NULL;
		}
193 194
	}

195
	mutex_destroy(&ctx->lock);
196
	kfree(ctx);
197 198
}

199 200
int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
			  u32 ring, struct drm_sched_entity **entity)
201
{
202 203
	int r;

204 205 206 207
	if (hw_ip >= AMDGPU_HW_IP_NUM) {
		DRM_ERROR("unknown HW IP type: %d\n", hw_ip);
		return -EINVAL;
	}
208 209 210 211 212 213 214

	/* Right now all IPs have only one instance - multiple rings. */
	if (instance != 0) {
		DRM_DEBUG("invalid ip instance: %d\n", instance);
		return -EINVAL;
	}

215 216
	if (ring >= amdgpu_ctx_num_entities[hw_ip]) {
		DRM_DEBUG("invalid ring: %d %d\n", hw_ip, ring);
217 218 219
		return -EINVAL;
	}

220 221 222 223 224 225 226
	if (ctx->entities[hw_ip][ring] == NULL) {
		r = amdgpu_ctx_init_entity(ctx, hw_ip, ring);
		if (r)
			return r;
	}

	*entity = &ctx->entities[hw_ip][ring]->entity;
227 228 229
	return 0;
}

230 231
static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
			    struct amdgpu_fpriv *fpriv,
232
			    struct drm_file *filp,
233
			    enum drm_sched_priority priority,
234 235 236
			    uint32_t *id)
{
	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
A
Alex Deucher 已提交
237
	struct amdgpu_ctx *ctx;
238
	int r;
A
Alex Deucher 已提交
239

240 241 242 243 244
	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	mutex_lock(&mgr->lock);
245
	r = idr_alloc(&mgr->ctx_handles, ctx, 1, AMDGPU_VM_MAX_NUM_CTX, GFP_KERNEL);
246
	if (r < 0) {
247
		mutex_unlock(&mgr->lock);
248 249 250
		kfree(ctx);
		return r;
	}
251

252
	*id = (uint32_t)r;
253
	r = amdgpu_ctx_init(adev, priority, filp, ctx);
254 255 256 257 258
	if (r) {
		idr_remove(&mgr->ctx_handles, *id);
		*id = 0;
		kfree(ctx);
	}
259 260 261 262 263 264 265
	mutex_unlock(&mgr->lock);
	return r;
}

static void amdgpu_ctx_do_release(struct kref *ref)
{
	struct amdgpu_ctx *ctx;
266
	u32 i, j;
267 268

	ctx = container_of(ref, struct amdgpu_ctx, refcount);
269 270 271 272
	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
			if (!ctx->entities[i][j])
				continue;
273

274 275 276
			drm_sched_entity_destroy(&ctx->entities[i][j]->entity);
		}
	}
277

278
	amdgpu_ctx_fini(ref);
279 280 281 282 283 284 285 286
}

static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id)
{
	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
	struct amdgpu_ctx *ctx;

	mutex_lock(&mgr->lock);
287 288
	ctx = idr_remove(&mgr->ctx_handles, id);
	if (ctx)
289
		kref_put(&ctx->refcount, amdgpu_ctx_do_release);
290
	mutex_unlock(&mgr->lock);
291
	return ctx ? 0 : -EINVAL;
A
Alex Deucher 已提交
292 293
}

294 295 296
static int amdgpu_ctx_query(struct amdgpu_device *adev,
			    struct amdgpu_fpriv *fpriv, uint32_t id,
			    union drm_amdgpu_ctx_out *out)
A
Alex Deucher 已提交
297 298
{
	struct amdgpu_ctx *ctx;
299
	struct amdgpu_ctx_mgr *mgr;
300
	unsigned reset_counter;
A
Alex Deucher 已提交
301

302 303 304 305
	if (!fpriv)
		return -EINVAL;

	mgr = &fpriv->ctx_mgr;
306
	mutex_lock(&mgr->lock);
A
Alex Deucher 已提交
307
	ctx = idr_find(&mgr->ctx_handles, id);
308
	if (!ctx) {
309
		mutex_unlock(&mgr->lock);
310
		return -EINVAL;
A
Alex Deucher 已提交
311
	}
312 313

	/* TODO: these two are always zero */
314 315
	out->state.flags = 0x0;
	out->state.hangs = 0x0;
316 317 318 319

	/* determine if a GPU reset has occured since the last call */
	reset_counter = atomic_read(&adev->gpu_reset_counter);
	/* TODO: this should ideally return NO, GUILTY, or INNOCENT. */
320
	if (ctx->reset_counter_query == reset_counter)
321 322 323
		out->state.reset_status = AMDGPU_CTX_NO_RESET;
	else
		out->state.reset_status = AMDGPU_CTX_UNKNOWN_RESET;
324
	ctx->reset_counter_query = reset_counter;
325

326
	mutex_unlock(&mgr->lock);
327
	return 0;
A
Alex Deucher 已提交
328 329
}

M
Monk Liu 已提交
330 331 332 333 334 335
static int amdgpu_ctx_query2(struct amdgpu_device *adev,
	struct amdgpu_fpriv *fpriv, uint32_t id,
	union drm_amdgpu_ctx_out *out)
{
	struct amdgpu_ctx *ctx;
	struct amdgpu_ctx_mgr *mgr;
336
	unsigned long ras_counter;
M
Monk Liu 已提交
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360

	if (!fpriv)
		return -EINVAL;

	mgr = &fpriv->ctx_mgr;
	mutex_lock(&mgr->lock);
	ctx = idr_find(&mgr->ctx_handles, id);
	if (!ctx) {
		mutex_unlock(&mgr->lock);
		return -EINVAL;
	}

	out->state.flags = 0x0;
	out->state.hangs = 0x0;

	if (ctx->reset_counter != atomic_read(&adev->gpu_reset_counter))
		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RESET;

	if (ctx->vram_lost_counter != atomic_read(&adev->vram_lost_counter))
		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST;

	if (atomic_read(&ctx->guilty))
		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
	/*query ue count*/
	ras_counter = amdgpu_ras_query_error_count(adev, false);
	/*ras counter is monotonic increasing*/
	if (ras_counter != ctx->ras_counter_ue) {
		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE;
		ctx->ras_counter_ue = ras_counter;
	}

	/*query ce count*/
	ras_counter = amdgpu_ras_query_error_count(adev, true);
	if (ras_counter != ctx->ras_counter_ce) {
		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE;
		ctx->ras_counter_ce = ras_counter;
	}

M
Monk Liu 已提交
376 377 378 379
	mutex_unlock(&mgr->lock);
	return 0;
}

A
Alex Deucher 已提交
380
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
381
		     struct drm_file *filp)
A
Alex Deucher 已提交
382 383 384
{
	int r;
	uint32_t id;
385
	enum drm_sched_priority priority;
A
Alex Deucher 已提交
386 387 388 389 390 391

	union drm_amdgpu_ctx *args = data;
	struct amdgpu_device *adev = dev->dev_private;
	struct amdgpu_fpriv *fpriv = filp->driver_priv;

	id = args->in.ctx_id;
392
	r = amdgpu_to_sched_priority(args->in.priority, &priority);
393

394 395
	/* For backwards compatibility reasons, we need to accept
	 * ioctls with garbage in the priority field */
396
	if (r == -EINVAL)
397
		priority = DRM_SCHED_PRIORITY_NORMAL;
A
Alex Deucher 已提交
398 399

	switch (args->in.op) {
400
	case AMDGPU_CTX_OP_ALLOC_CTX:
401
		r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
402 403 404 405 406 407 408 409
		args->out.alloc.ctx_id = id;
		break;
	case AMDGPU_CTX_OP_FREE_CTX:
		r = amdgpu_ctx_free(fpriv, id);
		break;
	case AMDGPU_CTX_OP_QUERY_STATE:
		r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
		break;
M
Monk Liu 已提交
410 411 412
	case AMDGPU_CTX_OP_QUERY_STATE2:
		r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
		break;
413 414
	default:
		return -EINVAL;
A
Alex Deucher 已提交
415 416 417 418
	}

	return r;
}
419 420 421 422

struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id)
{
	struct amdgpu_ctx *ctx;
423 424 425 426 427 428
	struct amdgpu_ctx_mgr *mgr;

	if (!fpriv)
		return NULL;

	mgr = &fpriv->ctx_mgr;
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445

	mutex_lock(&mgr->lock);
	ctx = idr_find(&mgr->ctx_handles, id);
	if (ctx)
		kref_get(&ctx->refcount);
	mutex_unlock(&mgr->lock);
	return ctx;
}

int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
{
	if (ctx == NULL)
		return -EINVAL;

	kref_put(&ctx->refcount, amdgpu_ctx_do_release);
	return 0;
}
446

447 448 449
void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
			  struct drm_sched_entity *entity,
			  struct dma_fence *fence, uint64_t* handle)
450
{
451 452
	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
	uint64_t seq = centity->sequence;
453
	struct dma_fence *other = NULL;
454
	unsigned idx = 0;
455

456
	idx = seq & (amdgpu_sched_jobs - 1);
457
	other = centity->fences[idx];
458 459
	if (other)
		BUG_ON(!dma_fence_is_signaled(other));
460

461
	dma_fence_get(fence);
462 463

	spin_lock(&ctx->ring_lock);
464 465
	centity->fences[idx] = fence;
	centity->sequence++;
466 467
	spin_unlock(&ctx->ring_lock);

468
	dma_fence_put(other);
469 470
	if (handle)
		*handle = seq;
471 472
}

473
struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
474 475
				       struct drm_sched_entity *entity,
				       uint64_t seq)
476
{
477
	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
478
	struct dma_fence *fence;
479 480

	spin_lock(&ctx->ring_lock);
481

M
Monk Liu 已提交
482
	if (seq == ~0ull)
483
		seq = centity->sequence - 1;
M
Monk Liu 已提交
484

485
	if (seq >= centity->sequence) {
486 487 488 489
		spin_unlock(&ctx->ring_lock);
		return ERR_PTR(-EINVAL);
	}

490

491
	if (seq + amdgpu_sched_jobs < centity->sequence) {
492 493 494 495
		spin_unlock(&ctx->ring_lock);
		return NULL;
	}

496
	fence = dma_fence_get(centity->fences[seq & (amdgpu_sched_jobs - 1)]);
497 498 499 500
	spin_unlock(&ctx->ring_lock);

	return fence;
}
501

502 503 504 505 506 507
static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx,
					    struct amdgpu_ctx_entity *aentity,
					    int hw_ip,
					    enum drm_sched_priority priority)
{
	struct amdgpu_device *adev = ctx->adev;
508
	unsigned int hw_prio;
509 510 511 512 513 514 515 516
	struct drm_gpu_scheduler **scheds = NULL;
	unsigned num_scheds;

	/* set sw priority */
	drm_sched_entity_set_priority(&aentity->entity, priority);

	/* set hw priority */
	if (hw_ip == AMDGPU_HW_IP_COMPUTE) {
517 518 519 520 521
		hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority,
						      AMDGPU_HW_IP_COMPUTE);
		hw_prio = array_index_nospec(hw_prio, AMDGPU_RING_PRIO_MAX);
		scheds = adev->gpu_sched[hw_ip][hw_prio].sched;
		num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds;
522 523 524 525 526
		drm_sched_entity_modify_sched(&aentity->entity, scheds,
					      num_scheds);
	}
}

527
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
528
				  enum drm_sched_priority priority)
529
{
530
	enum drm_sched_priority ctx_prio;
531
	unsigned i, j;
532 533 534

	ctx->override_priority = priority;

535
	ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
536
			ctx->init_priority : ctx->override_priority;
537 538 539 540
	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
			if (!ctx->entities[i][j])
				continue;
541

542 543
			amdgpu_ctx_set_entity_priority(ctx, ctx->entities[i][j],
						       i, ctx_prio);
544
		}
545 546 547
	}
}

548 549
int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
			       struct drm_sched_entity *entity)
550
{
551
	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
552 553 554
	struct dma_fence *other;
	unsigned idx;
	long r;
555

556 557 558 559
	spin_lock(&ctx->ring_lock);
	idx = centity->sequence & (amdgpu_sched_jobs - 1);
	other = dma_fence_get(centity->fences[idx]);
	spin_unlock(&ctx->ring_lock);
560

561 562
	if (!other)
		return 0;
563

564 565 566 567 568 569
	r = dma_fence_wait(other, true);
	if (r < 0 && r != -ERESTARTSYS)
		DRM_ERROR("Error (%ld) waiting for fence!\n", r);

	dma_fence_put(other);
	return r;
570 571
}

572 573 574 575 576 577
void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
{
	mutex_init(&mgr->lock);
	idr_init(&mgr->ctx_handles);
}

578
long amdgpu_ctx_mgr_entity_flush(struct amdgpu_ctx_mgr *mgr, long timeout)
579 580 581
{
	struct amdgpu_ctx *ctx;
	struct idr *idp;
582
	uint32_t id, i, j;
583 584 585

	idp = &mgr->ctx_handles;

586
	mutex_lock(&mgr->lock);
587
	idr_for_each_entry(idp, ctx, id) {
588 589 590 591 592 593
		for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
			for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
				struct drm_sched_entity *entity;

				if (!ctx->entities[i][j])
					continue;
594

595 596 597
				entity = &ctx->entities[i][j]->entity;
				timeout = drm_sched_entity_flush(entity, timeout);
			}
598
		}
599
	}
600
	mutex_unlock(&mgr->lock);
601
	return timeout;
602 603
}

604
void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
605 606 607
{
	struct amdgpu_ctx *ctx;
	struct idr *idp;
608
	uint32_t id, i, j;
609 610 611 612

	idp = &mgr->ctx_handles;

	idr_for_each_entry(idp, ctx, id) {
613 614 615
		if (kref_read(&ctx->refcount) != 1) {
			DRM_ERROR("ctx %p is still alive\n", ctx);
			continue;
616
		}
617

618 619 620 621 622 623 624 625 626 627 628
		for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
			for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
				struct drm_sched_entity *entity;

				if (!ctx->entities[i][j])
					continue;

				entity = &ctx->entities[i][j]->entity;
				drm_sched_entity_fini(entity);
			}
		}
629 630 631
	}
}

632 633 634 635 636 637
void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr)
{
	struct amdgpu_ctx *ctx;
	struct idr *idp;
	uint32_t id;

638
	amdgpu_ctx_mgr_entity_fini(mgr);
639

640 641 642
	idp = &mgr->ctx_handles;

	idr_for_each_entry(idp, ctx, id) {
643
		if (kref_put(&ctx->refcount, amdgpu_ctx_fini) != 1)
644 645 646 647 648 649
			DRM_ERROR("ctx %p is still alive\n", ctx);
	}

	idr_destroy(&mgr->ctx_handles);
	mutex_destroy(&mgr->lock);
}