1/*	$NetBSD: amdgpu_ctx.c,v 1.8 2021/12/19 12:38:41 riastradh Exp $	*/
2
3/*
4 * Copyright 2015 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: monk liu <monk.liu@amd.com>
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: amdgpu_ctx.c,v 1.8 2021/12/19 12:38:41 riastradh Exp $");
29
30#include <drm/drm_auth.h>
31#include "amdgpu.h"
32#include "amdgpu_sched.h"
33#include "amdgpu_ras.h"
34
35#include <linux/nbsd-namespace.h>
36#define to_amdgpu_ctx_entity(e)	\
37	container_of((e), struct amdgpu_ctx_entity, entity)
38
39const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = {
40	[AMDGPU_HW_IP_GFX]	=	1,
41	[AMDGPU_HW_IP_COMPUTE]	=	4,
42	[AMDGPU_HW_IP_DMA]	=	2,
43	[AMDGPU_HW_IP_UVD]	=	1,
44	[AMDGPU_HW_IP_VCE]	=	1,
45	[AMDGPU_HW_IP_UVD_ENC]	=	1,
46	[AMDGPU_HW_IP_VCN_DEC]	=	1,
47	[AMDGPU_HW_IP_VCN_ENC]	=	1,
48	[AMDGPU_HW_IP_VCN_JPEG]	=	1,
49};
50
51static int amdgpu_ctx_priority_permit(struct drm_file *filp,
52				      enum drm_sched_priority priority)
53{
54	if (priority < 0 || priority >= DRM_SCHED_PRIORITY_MAX)
55		return -EINVAL;
56
57	/* NORMAL and below are accessible by everyone */
58	if (priority <= DRM_SCHED_PRIORITY_NORMAL)
59		return 0;
60
61	if (capable(CAP_SYS_NICE))
62		return 0;
63
64	if (drm_is_current_master(filp))
65		return 0;
66
67	return -EACCES;
68}
69
70static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, const u32 hw_ip, const u32 ring)
71{
72	struct amdgpu_device *adev = ctx->adev;
73	struct amdgpu_ctx_entity *entity;
74	struct drm_gpu_scheduler **scheds = NULL, *sched = NULL;
75	unsigned num_scheds = 0;
76	enum drm_sched_priority priority;
77	int r;
78
79	entity = kcalloc(1, offsetof(typeof(*entity), fences[amdgpu_sched_jobs]),
80			 GFP_KERNEL);
81	if (!entity)
82		return  -ENOMEM;
83
84	entity->sequence = 1;
85	priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
86				ctx->init_priority : ctx->override_priority;
87	switch (hw_ip) {
88		case AMDGPU_HW_IP_GFX:
89			sched = &adev->gfx.gfx_ring[0].sched;
90			scheds = &sched;
91			num_scheds = 1;
92			break;
93		case AMDGPU_HW_IP_COMPUTE:
94			scheds = adev->gfx.compute_sched;
95			num_scheds = adev->gfx.num_compute_sched;
96			break;
97		case AMDGPU_HW_IP_DMA:
98			scheds = adev->sdma.sdma_sched;
99			num_scheds = adev->sdma.num_sdma_sched;
100			break;
101		case AMDGPU_HW_IP_UVD:
102			sched = &adev->uvd.inst[0].ring.sched;
103			scheds = &sched;
104			num_scheds = 1;
105			break;
106		case AMDGPU_HW_IP_VCE:
107			sched = &adev->vce.ring[0].sched;
108			scheds = &sched;
109			num_scheds = 1;
110			break;
111		case AMDGPU_HW_IP_UVD_ENC:
112			sched = &adev->uvd.inst[0].ring_enc[0].sched;
113			scheds = &sched;
114			num_scheds = 1;
115			break;
116		case AMDGPU_HW_IP_VCN_DEC:
117			scheds = adev->vcn.vcn_dec_sched;
118			num_scheds =  adev->vcn.num_vcn_dec_sched;
119			break;
120		case AMDGPU_HW_IP_VCN_ENC:
121			scheds = adev->vcn.vcn_enc_sched;
122			num_scheds =  adev->vcn.num_vcn_enc_sched;
123			break;
124		case AMDGPU_HW_IP_VCN_JPEG:
125			scheds = adev->jpeg.jpeg_sched;
126			num_scheds =  adev->jpeg.num_jpeg_sched;
127			break;
128	}
129
130	r = drm_sched_entity_init(&entity->entity, priority, scheds, num_scheds,
131				  &ctx->guilty);
132	if (r)
133		goto error_free_entity;
134
135	ctx->entities[hw_ip][ring] = entity;
136	return 0;
137
138error_free_entity:
139	kfree(entity);
140
141	return r;
142}
143
144static int amdgpu_ctx_init(struct amdgpu_device *adev,
145			   enum drm_sched_priority priority,
146			   struct drm_file *filp,
147			   struct amdgpu_ctx *ctx)
148{
149	int r;
150
151	r = amdgpu_ctx_priority_permit(filp, priority);
152	if (r)
153		return r;
154
155	memset(ctx, 0, sizeof(*ctx));
156
157	ctx->adev = adev;
158
159	kref_init(&ctx->refcount);
160	spin_lock_init(&ctx->ring_lock);
161	mutex_init(&ctx->lock);
162
163	ctx->reset_counter = atomic_read(&adev->gpu_reset_counter);
164	ctx->reset_counter_query = ctx->reset_counter;
165	ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
166	ctx->init_priority = priority;
167	ctx->override_priority = DRM_SCHED_PRIORITY_UNSET;
168
169	return 0;
170
171}
172
173static void amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity)
174{
175
176	int i;
177
178	if (!entity)
179		return;
180
181	for (i = 0; i < amdgpu_sched_jobs; ++i)
182		dma_fence_put(entity->fences[i]);
183
184	kfree(entity);
185}
186
187static void amdgpu_ctx_fini(struct kref *ref)
188{
189	struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount);
190	struct amdgpu_device *adev = ctx->adev;
191	unsigned i, j;
192
193	if (!adev)
194		return;
195
196	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
197		for (j = 0; j < AMDGPU_MAX_ENTITY_NUM; ++j) {
198			amdgpu_ctx_fini_entity(ctx->entities[i][j]);
199			ctx->entities[i][j] = NULL;
200		}
201	}
202
203	mutex_destroy(&ctx->lock);
204	spin_lock_destroy(&ctx->ring_lock);
205	kfree(ctx);
206}
207
208int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance,
209			  u32 ring, struct drm_sched_entity **entity)
210{
211	int r;
212
213	if (hw_ip >= AMDGPU_HW_IP_NUM) {
214		DRM_ERROR("unknown HW IP type: %d\n", hw_ip);
215		return -EINVAL;
216	}
217
218	/* Right now all IPs have only one instance - multiple rings. */
219	if (instance != 0) {
220		DRM_DEBUG("invalid ip instance: %d\n", instance);
221		return -EINVAL;
222	}
223
224	if (ring >= amdgpu_ctx_num_entities[hw_ip]) {
225		DRM_DEBUG("invalid ring: %d %d\n", hw_ip, ring);
226		return -EINVAL;
227	}
228
229	if (ctx->entities[hw_ip][ring] == NULL) {
230		r = amdgpu_ctx_init_entity(ctx, hw_ip, ring);
231		if (r)
232			return r;
233	}
234
235	*entity = &ctx->entities[hw_ip][ring]->entity;
236	return 0;
237}
238
239static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
240			    struct amdgpu_fpriv *fpriv,
241			    struct drm_file *filp,
242			    enum drm_sched_priority priority,
243			    uint32_t *id)
244{
245	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
246	struct amdgpu_ctx *ctx;
247	int r;
248
249	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
250	if (!ctx)
251		return -ENOMEM;
252
253	idr_preload(GFP_KERNEL);
254	mutex_lock(&mgr->lock);
255	r = idr_alloc(&mgr->ctx_handles, ctx, 1, AMDGPU_VM_MAX_NUM_CTX, GFP_KERNEL);
256	if (r < 0) {
257		mutex_unlock(&mgr->lock);
258		idr_preload_end();
259		kfree(ctx);
260		return r;
261	}
262
263	*id = (uint32_t)r;
264	r = amdgpu_ctx_init(adev, priority, filp, ctx);
265	if (r) {
266		idr_remove(&mgr->ctx_handles, *id);
267		*id = 0;
268		kfree(ctx);
269	}
270	mutex_unlock(&mgr->lock);
271	idr_preload_end();
272
273	return r;
274}
275
276static void amdgpu_ctx_do_release(struct kref *ref)
277{
278	struct amdgpu_ctx *ctx;
279	u32 i, j;
280
281	ctx = container_of(ref, struct amdgpu_ctx, refcount);
282	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
283		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
284			if (!ctx->entities[i][j])
285				continue;
286
287			drm_sched_entity_destroy(&ctx->entities[i][j]->entity);
288		}
289	}
290
291	amdgpu_ctx_fini(ref);
292}
293
294static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id)
295{
296	struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
297	struct amdgpu_ctx *ctx;
298
299	mutex_lock(&mgr->lock);
300	ctx = idr_remove(&mgr->ctx_handles, id);
301	if (ctx)
302		kref_put(&ctx->refcount, amdgpu_ctx_do_release);
303	mutex_unlock(&mgr->lock);
304	return ctx ? 0 : -EINVAL;
305}
306
307static int amdgpu_ctx_query(struct amdgpu_device *adev,
308			    struct amdgpu_fpriv *fpriv, uint32_t id,
309			    union drm_amdgpu_ctx_out *out)
310{
311	struct amdgpu_ctx *ctx;
312	struct amdgpu_ctx_mgr *mgr;
313	unsigned reset_counter;
314
315	if (!fpriv)
316		return -EINVAL;
317
318	mgr = &fpriv->ctx_mgr;
319	mutex_lock(&mgr->lock);
320	ctx = idr_find(&mgr->ctx_handles, id);
321	if (!ctx) {
322		mutex_unlock(&mgr->lock);
323		return -EINVAL;
324	}
325
326	/* TODO: these two are always zero */
327	out->state.flags = 0x0;
328	out->state.hangs = 0x0;
329
330	/* determine if a GPU reset has occured since the last call */
331	reset_counter = atomic_read(&adev->gpu_reset_counter);
332	/* TODO: this should ideally return NO, GUILTY, or INNOCENT. */
333	if (ctx->reset_counter_query == reset_counter)
334		out->state.reset_status = AMDGPU_CTX_NO_RESET;
335	else
336		out->state.reset_status = AMDGPU_CTX_UNKNOWN_RESET;
337	ctx->reset_counter_query = reset_counter;
338
339	mutex_unlock(&mgr->lock);
340	return 0;
341}
342
343static int amdgpu_ctx_query2(struct amdgpu_device *adev,
344	struct amdgpu_fpriv *fpriv, uint32_t id,
345	union drm_amdgpu_ctx_out *out)
346{
347	struct amdgpu_ctx *ctx;
348	struct amdgpu_ctx_mgr *mgr;
349	unsigned long ras_counter;
350
351	if (!fpriv)
352		return -EINVAL;
353
354	mgr = &fpriv->ctx_mgr;
355	mutex_lock(&mgr->lock);
356	ctx = idr_find(&mgr->ctx_handles, id);
357	if (!ctx) {
358		mutex_unlock(&mgr->lock);
359		return -EINVAL;
360	}
361
362	out->state.flags = 0x0;
363	out->state.hangs = 0x0;
364
365	if (ctx->reset_counter != atomic_read(&adev->gpu_reset_counter))
366		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RESET;
367
368	if (ctx->vram_lost_counter != atomic_read(&adev->vram_lost_counter))
369		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST;
370
371	if (atomic_read(&ctx->guilty))
372		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
373
374	/*query ue count*/
375	ras_counter = amdgpu_ras_query_error_count(adev, false);
376	/*ras counter is monotonic increasing*/
377	if (ras_counter != ctx->ras_counter_ue) {
378		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE;
379		ctx->ras_counter_ue = ras_counter;
380	}
381
382	/*query ce count*/
383	ras_counter = amdgpu_ras_query_error_count(adev, true);
384	if (ras_counter != ctx->ras_counter_ce) {
385		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE;
386		ctx->ras_counter_ce = ras_counter;
387	}
388
389	mutex_unlock(&mgr->lock);
390	return 0;
391}
392
393int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
394		     struct drm_file *filp)
395{
396	int r;
397	uint32_t id;
398	enum drm_sched_priority priority;
399
400	union drm_amdgpu_ctx *args = data;
401	struct amdgpu_device *adev = dev->dev_private;
402	struct amdgpu_fpriv *fpriv = filp->driver_priv;
403
404	r = 0;
405	id = args->in.ctx_id;
406	priority = amdgpu_to_sched_priority(args->in.priority);
407
408	/* For backwards compatibility reasons, we need to accept
409	 * ioctls with garbage in the priority field */
410	if (priority == DRM_SCHED_PRIORITY_INVALID)
411		priority = DRM_SCHED_PRIORITY_NORMAL;
412
413	switch (args->in.op) {
414	case AMDGPU_CTX_OP_ALLOC_CTX:
415		r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
416		args->out.alloc.ctx_id = id;
417		break;
418	case AMDGPU_CTX_OP_FREE_CTX:
419		r = amdgpu_ctx_free(fpriv, id);
420		break;
421	case AMDGPU_CTX_OP_QUERY_STATE:
422		r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
423		break;
424	case AMDGPU_CTX_OP_QUERY_STATE2:
425		r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
426		break;
427	default:
428		return -EINVAL;
429	}
430
431	return r;
432}
433
434struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t id)
435{
436	struct amdgpu_ctx *ctx;
437	struct amdgpu_ctx_mgr *mgr;
438
439	if (!fpriv)
440		return NULL;
441
442	mgr = &fpriv->ctx_mgr;
443
444	mutex_lock(&mgr->lock);
445	ctx = idr_find(&mgr->ctx_handles, id);
446	if (ctx)
447		kref_get(&ctx->refcount);
448	mutex_unlock(&mgr->lock);
449	return ctx;
450}
451
452int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
453{
454	if (ctx == NULL)
455		return -EINVAL;
456
457	kref_put(&ctx->refcount, amdgpu_ctx_do_release);
458	return 0;
459}
460
461void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
462			  struct drm_sched_entity *entity,
463			  struct dma_fence *fence, uint64_t* handle)
464{
465	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
466	uint64_t seq;
467	struct dma_fence *other = NULL;
468	unsigned idx = 0;
469
470	spin_lock(&ctx->ring_lock);
471	seq = centity->sequence;
472	idx = seq & (amdgpu_sched_jobs - 1);
473	other = centity->fences[idx];
474	if (other)
475		BUG_ON(!dma_fence_is_signaled(other));
476
477	dma_fence_get(fence);
478	centity->fences[idx] = fence;
479	centity->sequence++;
480	spin_unlock(&ctx->ring_lock);
481
482	dma_fence_put(other);
483	if (handle)
484		*handle = seq;
485}
486
487struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
488				       struct drm_sched_entity *entity,
489				       uint64_t seq)
490{
491	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
492	struct dma_fence *fence;
493
494	spin_lock(&ctx->ring_lock);
495
496	if (seq == ~0ull)
497		seq = centity->sequence - 1;
498
499	if (seq >= centity->sequence) {
500		spin_unlock(&ctx->ring_lock);
501		return ERR_PTR(-EINVAL);
502	}
503
504
505	if (seq + amdgpu_sched_jobs < centity->sequence) {
506		spin_unlock(&ctx->ring_lock);
507		return NULL;
508	}
509
510	fence = dma_fence_get(centity->fences[seq & (amdgpu_sched_jobs - 1)]);
511	spin_unlock(&ctx->ring_lock);
512
513	return fence;
514}
515
516void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx,
517				  enum drm_sched_priority priority)
518{
519	enum drm_sched_priority ctx_prio;
520	unsigned i, j;
521
522	ctx->override_priority = priority;
523
524	ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ?
525			ctx->init_priority : ctx->override_priority;
526	for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
527		for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
528			struct drm_sched_entity *entity;
529
530			if (!ctx->entities[i][j])
531				continue;
532
533			entity = &ctx->entities[i][j]->entity;
534			drm_sched_entity_set_priority(entity, ctx_prio);
535		}
536	}
537}
538
539int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx,
540			       struct drm_sched_entity *entity)
541{
542	struct amdgpu_ctx_entity *centity = to_amdgpu_ctx_entity(entity);
543	struct dma_fence *other;
544	unsigned idx;
545	long r;
546
547	spin_lock(&ctx->ring_lock);
548	idx = centity->sequence & (amdgpu_sched_jobs - 1);
549	other = dma_fence_get(centity->fences[idx]);
550	spin_unlock(&ctx->ring_lock);
551
552	if (!other)
553		return 0;
554
555	r = dma_fence_wait(other, true);
556	if (r < 0 && r != -ERESTARTSYS)
557		DRM_ERROR("Error (%ld) waiting for fence!\n", r);
558
559	dma_fence_put(other);
560	return r;
561}
562
563void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr)
564{
565	mutex_init(&mgr->lock);
566	idr_init(&mgr->ctx_handles);
567}
568
569long amdgpu_ctx_mgr_entity_flush(struct amdgpu_ctx_mgr *mgr, long timeout)
570{
571	struct amdgpu_ctx *ctx;
572	struct idr *idp;
573	uint32_t id, i, j;
574
575	idp = &mgr->ctx_handles;
576
577	mutex_lock(&mgr->lock);
578	idr_for_each_entry(idp, ctx, id) {
579		for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
580			for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
581				struct drm_sched_entity *entity;
582
583				if (!ctx->entities[i][j])
584					continue;
585
586				entity = &ctx->entities[i][j]->entity;
587				timeout = drm_sched_entity_flush(entity, timeout);
588			}
589		}
590	}
591	mutex_unlock(&mgr->lock);
592	return timeout;
593}
594
595void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
596{
597	struct amdgpu_ctx *ctx;
598	struct idr *idp;
599	uint32_t id, i, j;
600
601	idp = &mgr->ctx_handles;
602
603	idr_for_each_entry(idp, ctx, id) {
604		if (kref_read(&ctx->refcount) != 1) {
605			DRM_ERROR("ctx %p is still alive\n", ctx);
606			continue;
607		}
608
609		for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
610			for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
611				struct drm_sched_entity *entity;
612
613				if (!ctx->entities[i][j])
614					continue;
615
616				entity = &ctx->entities[i][j]->entity;
617				drm_sched_entity_fini(entity);
618			}
619		}
620	}
621}
622
623void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr)
624{
625	struct amdgpu_ctx *ctx;
626	struct idr *idp;
627	uint32_t id;
628
629	amdgpu_ctx_mgr_entity_fini(mgr);
630
631	idp = &mgr->ctx_handles;
632
633	idr_for_each_entry(idp, ctx, id) {
634		if (kref_put(&ctx->refcount, amdgpu_ctx_fini) != 1)
635			DRM_ERROR("ctx %p is still alive\n", ctx);
636	}
637
638	idr_destroy(&mgr->ctx_handles);
639	mutex_destroy(&mgr->lock);
640}
641
642void amdgpu_ctx_init_sched(struct amdgpu_device *adev)
643{
644	int i, j;
645
646	for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
647		adev->gfx.gfx_sched[i] = &adev->gfx.gfx_ring[i].sched;
648		adev->gfx.num_gfx_sched++;
649	}
650
651	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
652		adev->gfx.compute_sched[i] = &adev->gfx.compute_ring[i].sched;
653		adev->gfx.num_compute_sched++;
654	}
655
656	for (i = 0; i < adev->sdma.num_instances; i++) {
657		adev->sdma.sdma_sched[i] = &adev->sdma.instance[i].ring.sched;
658		adev->sdma.num_sdma_sched++;
659	}
660
661	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
662		if (adev->vcn.harvest_config & (1 << i))
663			continue;
664		adev->vcn.vcn_dec_sched[adev->vcn.num_vcn_dec_sched++] =
665			&adev->vcn.inst[i].ring_dec.sched;
666	}
667
668	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
669		if (adev->vcn.harvest_config & (1 << i))
670			continue;
671		for (j = 0; j < adev->vcn.num_enc_rings; ++j)
672			adev->vcn.vcn_enc_sched[adev->vcn.num_vcn_enc_sched++] =
673				&adev->vcn.inst[i].ring_enc[j].sched;
674	}
675
676	for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
677		if (adev->jpeg.harvest_config & (1 << i))
678			continue;
679		adev->jpeg.jpeg_sched[adev->jpeg.num_jpeg_sched++] =
680			&adev->jpeg.inst[i].ring_dec.sched;
681	}
682}
683