amdgpu_ctx.c 17.1 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"
A
Alex Deucher 已提交
29

30 31 32 33 34 35 36 37 38 39 40 41
#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,
42
	[AMDGPU_HW_IP_VCN_JPEG]	=	1,
43 44
};

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

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

	if (capable(CAP_SYS_NICE))
		return 0;

	if (drm_is_current_master(filp))
		return 0;

	return -EACCES;
}

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

75
static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, const u32 hw_ip, const u32 ring)
A
Alex Deucher 已提交
76
{
77 78 79 80
	struct amdgpu_device *adev = ctx->adev;
	struct amdgpu_ctx_entity *entity;
	struct drm_gpu_scheduler **scheds = NULL, *sched = NULL;
	unsigned num_scheds = 0;
81
	enum gfx_pipe_priority hw_prio;
82
	enum drm_sched_priority priority;
83
	int r;
A
Alex Deucher 已提交
84

85 86 87 88
	entity = kcalloc(1, offsetof(typeof(*entity), fences[amdgpu_sched_jobs]),
			 GFP_KERNEL);
	if (!entity)
		return  -ENOMEM;
89

90 91 92 93
	entity->sequence = 1;
	priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
				ctx->init_priority : ctx->override_priority;
	switch (hw_ip) {
94
		case AMDGPU_HW_IP_GFX:
95 96
			sched = &adev->gfx.gfx_ring[0].sched;
			scheds = &sched;
97
			num_scheds = 1;
98 99
			break;
		case AMDGPU_HW_IP_COMPUTE:
100 101 102
			hw_prio = amdgpu_ctx_sched_prio_to_compute_prio(priority);
			scheds = adev->gfx.compute_prio_sched[hw_prio];
			num_scheds = adev->gfx.num_compute_sched[hw_prio];
103 104
			break;
		case AMDGPU_HW_IP_DMA:
105 106
			scheds = adev->sdma.sdma_sched;
			num_scheds = adev->sdma.num_sdma_sched;
107 108
			break;
		case AMDGPU_HW_IP_UVD:
109 110 111
			sched = &adev->uvd.inst[0].ring.sched;
			scheds = &sched;
			num_scheds = 1;
112 113
			break;
		case AMDGPU_HW_IP_VCE:
114 115 116
			sched = &adev->vce.ring[0].sched;
			scheds = &sched;
			num_scheds = 1;
117 118
			break;
		case AMDGPU_HW_IP_UVD_ENC:
119 120 121
			sched = &adev->uvd.inst[0].ring_enc[0].sched;
			scheds = &sched;
			num_scheds = 1;
122 123
			break;
		case AMDGPU_HW_IP_VCN_DEC:
124 125
			scheds = adev->vcn.vcn_dec_sched;
			num_scheds =  adev->vcn.num_vcn_dec_sched;
126 127
			break;
		case AMDGPU_HW_IP_VCN_ENC:
128 129
			scheds = adev->vcn.vcn_enc_sched;
			num_scheds =  adev->vcn.num_vcn_enc_sched;
130 131
			break;
		case AMDGPU_HW_IP_VCN_JPEG:
132 133
			scheds = adev->jpeg.jpeg_sched;
			num_scheds =  adev->jpeg.num_jpeg_sched;
134
			break;
135 136
	}

137 138 139 140 141 142
	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 已提交
143
	return 0;
144

145 146
error_free_entity:
	kfree(entity);
147

148 149
	return r;
}
150

151 152 153 154 155 156
static int amdgpu_ctx_init(struct amdgpu_device *adev,
			   enum drm_sched_priority priority,
			   struct drm_file *filp,
			   struct amdgpu_ctx *ctx)
{
	int r;
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
	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 已提交
192 193
}

194
static void amdgpu_ctx_fini(struct kref *ref)
A
Alex Deucher 已提交
195
{
196
	struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount);
197 198 199
	struct amdgpu_device *adev = ctx->adev;
	unsigned i, j;

200 201 202
	if (!adev)
		return;

203 204 205 206 207
	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;
		}
208 209
	}

210
	mutex_destroy(&ctx->lock);
211
	kfree(ctx);
212 213
}

214 215
int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
			  u32 ring, struct drm_sched_entity **entity)
216
{
217 218
	int r;

219 220 221 222
	if (hw_ip >= AMDGPU_HW_IP_NUM) {
		DRM_ERROR("unknown HW IP type: %d\n", hw_ip);
		return -EINVAL;
	}
223 224 225 226 227 228 229

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

230 231
	if (ring >= amdgpu_ctx_num_entities[hw_ip]) {
		DRM_DEBUG("invalid ring: %d %d\n", hw_ip, ring);
232 233 234
		return -EINVAL;
	}

235 236 237 238 239 240 241
	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;
242 243 244
	return 0;
}

245 246
static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
			    struct amdgpu_fpriv *fpriv,
247
			    struct drm_file *filp,
248
			    enum drm_sched_priority priority,
249 250 251
			    uint32_t *id)
{
	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
A
Alex Deucher 已提交
252
	struct amdgpu_ctx *ctx;
253
	int r;
A
Alex Deucher 已提交
254

255 256 257 258 259
	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
		return -ENOMEM;

	mutex_lock(&mgr->lock);
260
	r = idr_alloc(&mgr->ctx_handles, ctx, 1, AMDGPU_VM_MAX_NUM_CTX, GFP_KERNEL);
261
	if (r < 0) {
262
		mutex_unlock(&mgr->lock);
263 264 265
		kfree(ctx);
		return r;
	}
266

267
	*id = (uint32_t)r;
268
	r = amdgpu_ctx_init(adev, priority, filp, ctx);
269 270 271 272 273
	if (r) {
		idr_remove(&mgr->ctx_handles, *id);
		*id = 0;
		kfree(ctx);
	}
274 275 276 277 278 279 280
	mutex_unlock(&mgr->lock);
	return r;
}

static void amdgpu_ctx_do_release(struct kref *ref)
{
	struct amdgpu_ctx *ctx;
281
	u32 i, j;
282 283

	ctx = container_of(ref, struct amdgpu_ctx, refcount);
284 285 286 287
	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;
288

289 290 291
			drm_sched_entity_destroy(&ctx->entities[i][j]->entity);
		}
	}
292

293
	amdgpu_ctx_fini(ref);
294 295 296 297 298 299 300 301
}

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);
302 303
	ctx = idr_remove(&mgr->ctx_handles, id);
	if (ctx)
304
		kref_put(&ctx->refcount, amdgpu_ctx_do_release);
305
	mutex_unlock(&mgr->lock);
306
	return ctx ? 0 : -EINVAL;
A
Alex Deucher 已提交
307 308
}

309 310 311
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 已提交
312 313
{
	struct amdgpu_ctx *ctx;
314
	struct amdgpu_ctx_mgr *mgr;
315
	unsigned reset_counter;
A
Alex Deucher 已提交
316

317 318 319 320
	if (!fpriv)
		return -EINVAL;

	mgr = &fpriv->ctx_mgr;
321
	mutex_lock(&mgr->lock);
A
Alex Deucher 已提交
322
	ctx = idr_find(&mgr->ctx_handles, id);
323
	if (!ctx) {
324
		mutex_unlock(&mgr->lock);
325
		return -EINVAL;
A
Alex Deucher 已提交
326
	}
327 328

	/* TODO: these two are always zero */
329 330
	out->state.flags = 0x0;
	out->state.hangs = 0x0;
331 332 333 334

	/* 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. */
335
	if (ctx->reset_counter_query == reset_counter)
336 337 338
		out->state.reset_status = AMDGPU_CTX_NO_RESET;
	else
		out->state.reset_status = AMDGPU_CTX_UNKNOWN_RESET;
339
	ctx->reset_counter_query = reset_counter;
340

341
	mutex_unlock(&mgr->lock);
342
	return 0;
A
Alex Deucher 已提交
343 344
}

M
Monk Liu 已提交
345 346 347 348 349 350
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;
351
	unsigned long ras_counter;
M
Monk Liu 已提交
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

	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;

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
	/*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 已提交
391 392 393 394
	mutex_unlock(&mgr->lock);
	return 0;
}

A
Alex Deucher 已提交
395
int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
396
		     struct drm_file *filp)
A
Alex Deucher 已提交
397 398 399
{
	int r;
	uint32_t id;
400
	enum drm_sched_priority priority;
A
Alex Deucher 已提交
401 402 403 404 405 406 407

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

	r = 0;
	id = args->in.ctx_id;
408 409
	priority = amdgpu_to_sched_priority(args->in.priority);

410 411
	/* For backwards compatibility reasons, we need to accept
	 * ioctls with garbage in the priority field */
412 413
	if (priority == DRM_SCHED_PRIORITY_INVALID)
		priority = DRM_SCHED_PRIORITY_NORMAL;
A
Alex Deucher 已提交
414 415

	switch (args->in.op) {
416
	case AMDGPU_CTX_OP_ALLOC_CTX:
417
		r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
418 419 420 421 422 423 424 425
		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 已提交
426 427 428
	case AMDGPU_CTX_OP_QUERY_STATE2:
		r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
		break;
429 430
	default:
		return -EINVAL;
A
Alex Deucher 已提交
431 432 433 434
	}

	return r;
}
435 436 437 438

struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id)
{
	struct amdgpu_ctx *ctx;
439 440 441 442 443 444
	struct amdgpu_ctx_mgr *mgr;

	if (!fpriv)
		return NULL;

	mgr = &fpriv->ctx_mgr;
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461

	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;
}
462

463 464 465
void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
			  struct drm_sched_entity *entity,
			  struct dma_fence *fence, uint64_t* handle)
466
{
467 468
	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
	uint64_t seq = centity->sequence;
469
	struct dma_fence *other = NULL;
470
	unsigned idx = 0;
471

472
	idx = seq & (amdgpu_sched_jobs - 1);
473
	other = centity->fences[idx];
474 475
	if (other)
		BUG_ON(!dma_fence_is_signaled(other));
476

477
	dma_fence_get(fence);
478 479

	spin_lock(&ctx->ring_lock);
480 481
	centity->fences[idx] = fence;
	centity->sequence++;
482 483
	spin_unlock(&ctx->ring_lock);

484
	dma_fence_put(other);
485 486
	if (handle)
		*handle = seq;
487 488
}

489
struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
490 491
				       struct drm_sched_entity *entity,
				       uint64_t seq)
492
{
493
	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
494
	struct dma_fence *fence;
495 496

	spin_lock(&ctx->ring_lock);
497

M
Monk Liu 已提交
498
	if (seq == ~0ull)
499
		seq = centity->sequence - 1;
M
Monk Liu 已提交
500

501
	if (seq >= centity->sequence) {
502 503 504 505
		spin_unlock(&ctx->ring_lock);
		return ERR_PTR(-EINVAL);
	}

506

507
	if (seq + amdgpu_sched_jobs < centity->sequence) {
508 509 510 511
		spin_unlock(&ctx->ring_lock);
		return NULL;
	}

512
	fence = dma_fence_get(centity->fences[seq & (amdgpu_sched_jobs - 1)]);
513 514 515 516
	spin_unlock(&ctx->ring_lock);

	return fence;
}
517

518
void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
519
				  enum drm_sched_priority priority)
520
{
521
	enum drm_sched_priority ctx_prio;
522
	unsigned i, j;
523 524 525

	ctx->override_priority = priority;

526
	ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
527
			ctx->init_priority : ctx->override_priority;
528 529 530
	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
			struct drm_sched_entity *entity;
531

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

535 536 537
			entity = &ctx->entities[i][j]->entity;
			drm_sched_entity_set_priority(entity, ctx_prio);
		}
538 539 540
	}
}

541 542
int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
			       struct drm_sched_entity *entity)
543
{
544
	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
545 546 547
	struct dma_fence *other;
	unsigned idx;
	long r;
548

549 550 551 552
	spin_lock(&ctx->ring_lock);
	idx = centity->sequence & (amdgpu_sched_jobs - 1);
	other = dma_fence_get(centity->fences[idx]);
	spin_unlock(&ctx->ring_lock);
553

554 555
	if (!other)
		return 0;
556

557 558 559 560 561 562
	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;
563 564
}

565 566 567 568 569 570
void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
{
	mutex_init(&mgr->lock);
	idr_init(&mgr->ctx_handles);
}

571
long amdgpu_ctx_mgr_entity_flush(struct amdgpu_ctx_mgr *mgr, long timeout)
572 573 574
{
	struct amdgpu_ctx *ctx;
	struct idr *idp;
575
	uint32_t id, i, j;
576 577 578

	idp = &mgr->ctx_handles;

579
	mutex_lock(&mgr->lock);
580
	idr_for_each_entry(idp, ctx, id) {
581 582 583 584 585 586
		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;
587

588 589 590
				entity = &ctx->entities[i][j]->entity;
				timeout = drm_sched_entity_flush(entity, timeout);
			}
591
		}
592
	}
593
	mutex_unlock(&mgr->lock);
594
	return timeout;
595 596
}

597
void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
598 599 600
{
	struct amdgpu_ctx *ctx;
	struct idr *idp;
601
	uint32_t id, i, j;
602 603 604 605

	idp = &mgr->ctx_handles;

	idr_for_each_entry(idp, ctx, id) {
606 607 608
		if (kref_read(&ctx->refcount) != 1) {
			DRM_ERROR("ctx %p is still alive\n", ctx);
			continue;
609
		}
610

611 612 613 614 615 616 617 618 619 620 621
		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);
			}
		}
622 623 624
	}
}

625 626 627 628 629 630
void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr)
{
	struct amdgpu_ctx *ctx;
	struct idr *idp;
	uint32_t id;

631
	amdgpu_ctx_mgr_entity_fini(mgr);
632

633 634 635
	idp = &mgr->ctx_handles;

	idr_for_each_entry(idp, ctx, id) {
636
		if (kref_put(&ctx->refcount, amdgpu_ctx_fini) != 1)
637 638 639 640 641 642
			DRM_ERROR("ctx %p is still alive\n", ctx);
	}

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

644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673

static void amdgpu_ctx_init_compute_sched(struct amdgpu_device *adev)
{
	int num_compute_sched_normal = 0;
	int num_compute_sched_high = AMDGPU_MAX_COMPUTE_RINGS - 1;
	int i;

	/* use one drm sched array, gfx.compute_sched to store both high and
	 * normal priority drm compute schedulers */
	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
		if (!adev->gfx.compute_ring[i].has_high_prio)
			adev->gfx.compute_sched[num_compute_sched_normal++] =
				&adev->gfx.compute_ring[i].sched;
		else
			adev->gfx.compute_sched[num_compute_sched_high--] =
				&adev->gfx.compute_ring[i].sched;
	}

	/* compute ring only has two priority for now */
	i = AMDGPU_GFX_PIPE_PRIO_NORMAL;
	adev->gfx.compute_prio_sched[i] = &adev->gfx.compute_sched[0];
	adev->gfx.num_compute_sched[i] = num_compute_sched_normal;

	i = AMDGPU_GFX_PIPE_PRIO_HIGH;
	adev->gfx.compute_prio_sched[i] =
		&adev->gfx.compute_sched[num_compute_sched_high - 1];
	adev->gfx.num_compute_sched[i] =
		adev->gfx.num_compute_rings - num_compute_sched_normal;
}

674 675 676 677
void amdgpu_ctx_init_sched(struct amdgpu_device *adev)
{
	int i, j;

678
	amdgpu_ctx_init_compute_sched(adev);
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
	for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
		adev->gfx.gfx_sched[i] = &adev->gfx.gfx_ring[i].sched;
		adev->gfx.num_gfx_sched++;
	}

	for (i = 0; i < adev->sdma.num_instances; i++) {
		adev->sdma.sdma_sched[i] = &adev->sdma.instance[i].ring.sched;
		adev->sdma.num_sdma_sched++;
	}

	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
		if (adev->vcn.harvest_config & (1 << i))
			continue;
		adev->vcn.vcn_dec_sched[adev->vcn.num_vcn_dec_sched++] =
			&adev->vcn.inst[i].ring_dec.sched;
	}

	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
		if (adev->vcn.harvest_config & (1 << i))
			continue;
		for (j = 0; j < adev->vcn.num_enc_rings; ++j)
			adev->vcn.vcn_enc_sched[adev->vcn.num_vcn_enc_sched++] =
				&adev->vcn.inst[i].ring_enc[j].sched;
	}

	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
		if (adev->jpeg.harvest_config & (1 << i))
			continue;
		adev->jpeg.jpeg_sched[adev->jpeg.num_jpeg_sched++] =
			&adev->jpeg.inst[i].ring_dec.sched;
	}
}