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