Commit 7122e505a52a2b1b8a21101cce04bcdf7c28deab
Merge branch 'drm-fixes-4.1' of git://people.freedesktop.org/~agd5f/linux into drm-fixes
Mostly stability fixes for UVD and VCE, plus a few other bug and regression fixes. * 'drm-fixes-4.1' of git://people.freedesktop.org/~agd5f/linux: drm/radeon: stop trying to suspend UVD sessions drm/radeon: more strictly validate the UVD codec drm/radeon: make UVD handle checking more strict drm/radeon: make VCE handle check more strict drm/radeon: fix userptr lockup drm/radeon: fix userptr BO unpin bug v3 drm/radeon: don't setup audio on asics that don't support it drm/radeon: disable semaphores for UVD V1 (v2)
Showing 11 changed files Side-by-side Diff
- drivers/gpu/drm/radeon/radeon.h
- drivers/gpu/drm/radeon/radeon_asic.c
- drivers/gpu/drm/radeon/radeon_asic.h
- drivers/gpu/drm/radeon/radeon_audio.c
- drivers/gpu/drm/radeon/radeon_mn.c
- drivers/gpu/drm/radeon/radeon_ttm.c
- drivers/gpu/drm/radeon/radeon_uvd.c
- drivers/gpu/drm/radeon/radeon_vce.c
- drivers/gpu/drm/radeon/rv770d.h
- drivers/gpu/drm/radeon/uvd_v1_0.c
- drivers/gpu/drm/radeon/uvd_v2_2.c
drivers/gpu/drm/radeon/radeon.h
... | ... | @@ -1673,7 +1673,6 @@ |
1673 | 1673 | struct radeon_bo *vcpu_bo; |
1674 | 1674 | void *cpu_addr; |
1675 | 1675 | uint64_t gpu_addr; |
1676 | - void *saved_bo; | |
1677 | 1676 | atomic_t handles[RADEON_MAX_UVD_HANDLES]; |
1678 | 1677 | struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; |
1679 | 1678 | unsigned img_size[RADEON_MAX_UVD_HANDLES]; |
drivers/gpu/drm/radeon/radeon_asic.c
... | ... | @@ -1202,7 +1202,7 @@ |
1202 | 1202 | static struct radeon_asic_ring rv770_uvd_ring = { |
1203 | 1203 | .ib_execute = &uvd_v1_0_ib_execute, |
1204 | 1204 | .emit_fence = &uvd_v2_2_fence_emit, |
1205 | - .emit_semaphore = &uvd_v1_0_semaphore_emit, | |
1205 | + .emit_semaphore = &uvd_v2_2_semaphore_emit, | |
1206 | 1206 | .cs_parse = &radeon_uvd_cs_parse, |
1207 | 1207 | .ring_test = &uvd_v1_0_ring_test, |
1208 | 1208 | .ib_test = &uvd_v1_0_ib_test, |
drivers/gpu/drm/radeon/radeon_asic.h
... | ... | @@ -949,6 +949,10 @@ |
949 | 949 | int uvd_v2_2_resume(struct radeon_device *rdev); |
950 | 950 | void uvd_v2_2_fence_emit(struct radeon_device *rdev, |
951 | 951 | struct radeon_fence *fence); |
952 | +bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, | |
953 | + struct radeon_ring *ring, | |
954 | + struct radeon_semaphore *semaphore, | |
955 | + bool emit_wait); | |
952 | 956 | |
953 | 957 | /* uvd v3.1 */ |
954 | 958 | bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, |
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/radeon/radeon_mn.c
drivers/gpu/drm/radeon/radeon_ttm.c
... | ... | @@ -591,8 +591,7 @@ |
591 | 591 | { |
592 | 592 | struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); |
593 | 593 | struct radeon_ttm_tt *gtt = (void *)ttm; |
594 | - struct scatterlist *sg; | |
595 | - int i; | |
594 | + struct sg_page_iter sg_iter; | |
596 | 595 | |
597 | 596 | int write = !(gtt->userflags & RADEON_GEM_USERPTR_READONLY); |
598 | 597 | enum dma_data_direction direction = write ? |
... | ... | @@ -605,9 +604,8 @@ |
605 | 604 | /* free the sg table and pages again */ |
606 | 605 | dma_unmap_sg(rdev->dev, ttm->sg->sgl, ttm->sg->nents, direction); |
607 | 606 | |
608 | - for_each_sg(ttm->sg->sgl, sg, ttm->sg->nents, i) { | |
609 | - struct page *page = sg_page(sg); | |
610 | - | |
607 | + for_each_sg_page(ttm->sg->sgl, &sg_iter, ttm->sg->nents, 0) { | |
608 | + struct page *page = sg_page_iter_page(&sg_iter); | |
611 | 609 | if (!(gtt->userflags & RADEON_GEM_USERPTR_READONLY)) |
612 | 610 | set_page_dirty(page); |
613 | 611 |
drivers/gpu/drm/radeon/radeon_uvd.c
... | ... | @@ -204,28 +204,32 @@ |
204 | 204 | |
205 | 205 | int radeon_uvd_suspend(struct radeon_device *rdev) |
206 | 206 | { |
207 | - unsigned size; | |
208 | - void *ptr; | |
209 | - int i; | |
207 | + int i, r; | |
210 | 208 | |
211 | 209 | if (rdev->uvd.vcpu_bo == NULL) |
212 | 210 | return 0; |
213 | 211 | |
214 | - for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) | |
215 | - if (atomic_read(&rdev->uvd.handles[i])) | |
216 | - break; | |
212 | + for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | |
213 | + uint32_t handle = atomic_read(&rdev->uvd.handles[i]); | |
214 | + if (handle != 0) { | |
215 | + struct radeon_fence *fence; | |
217 | 216 | |
218 | - if (i == RADEON_MAX_UVD_HANDLES) | |
219 | - return 0; | |
217 | + radeon_uvd_note_usage(rdev); | |
220 | 218 | |
221 | - size = radeon_bo_size(rdev->uvd.vcpu_bo); | |
222 | - size -= rdev->uvd_fw->size; | |
219 | + r = radeon_uvd_get_destroy_msg(rdev, | |
220 | + R600_RING_TYPE_UVD_INDEX, handle, &fence); | |
221 | + if (r) { | |
222 | + DRM_ERROR("Error destroying UVD (%d)!\n", r); | |
223 | + continue; | |
224 | + } | |
223 | 225 | |
224 | - ptr = rdev->uvd.cpu_addr; | |
225 | - ptr += rdev->uvd_fw->size; | |
226 | + radeon_fence_wait(fence, false); | |
227 | + radeon_fence_unref(&fence); | |
226 | 228 | |
227 | - rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); | |
228 | - memcpy(rdev->uvd.saved_bo, ptr, size); | |
229 | + rdev->uvd.filp[i] = NULL; | |
230 | + atomic_set(&rdev->uvd.handles[i], 0); | |
231 | + } | |
232 | + } | |
229 | 233 | |
230 | 234 | return 0; |
231 | 235 | } |
... | ... | @@ -246,12 +250,7 @@ |
246 | 250 | ptr = rdev->uvd.cpu_addr; |
247 | 251 | ptr += rdev->uvd_fw->size; |
248 | 252 | |
249 | - if (rdev->uvd.saved_bo != NULL) { | |
250 | - memcpy(ptr, rdev->uvd.saved_bo, size); | |
251 | - kfree(rdev->uvd.saved_bo); | |
252 | - rdev->uvd.saved_bo = NULL; | |
253 | - } else | |
254 | - memset(ptr, 0, size); | |
253 | + memset(ptr, 0, size); | |
255 | 254 | |
256 | 255 | return 0; |
257 | 256 | } |
... | ... | @@ -396,6 +395,29 @@ |
396 | 395 | return 0; |
397 | 396 | } |
398 | 397 | |
398 | +static int radeon_uvd_validate_codec(struct radeon_cs_parser *p, | |
399 | + unsigned stream_type) | |
400 | +{ | |
401 | + switch (stream_type) { | |
402 | + case 0: /* H264 */ | |
403 | + case 1: /* VC1 */ | |
404 | + /* always supported */ | |
405 | + return 0; | |
406 | + | |
407 | + case 3: /* MPEG2 */ | |
408 | + case 4: /* MPEG4 */ | |
409 | + /* only since UVD 3 */ | |
410 | + if (p->rdev->family >= CHIP_PALM) | |
411 | + return 0; | |
412 | + | |
413 | + /* fall through */ | |
414 | + default: | |
415 | + DRM_ERROR("UVD codec not supported by hardware %d!\n", | |
416 | + stream_type); | |
417 | + return -EINVAL; | |
418 | + } | |
419 | +} | |
420 | + | |
399 | 421 | static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, |
400 | 422 | unsigned offset, unsigned buf_sizes[]) |
401 | 423 | { |
402 | 424 | |
403 | 425 | |
404 | 426 | |
405 | 427 | |
406 | 428 | |
... | ... | @@ -436,50 +458,70 @@ |
436 | 458 | return -EINVAL; |
437 | 459 | } |
438 | 460 | |
439 | - if (msg_type == 1) { | |
440 | - /* it's a decode msg, calc buffer sizes */ | |
441 | - r = radeon_uvd_cs_msg_decode(msg, buf_sizes); | |
442 | - /* calc image size (width * height) */ | |
443 | - img_size = msg[6] * msg[7]; | |
461 | + switch (msg_type) { | |
462 | + case 0: | |
463 | + /* it's a create msg, calc image size (width * height) */ | |
464 | + img_size = msg[7] * msg[8]; | |
465 | + | |
466 | + r = radeon_uvd_validate_codec(p, msg[4]); | |
444 | 467 | radeon_bo_kunmap(bo); |
445 | 468 | if (r) |
446 | 469 | return r; |
447 | 470 | |
448 | - } else if (msg_type == 2) { | |
471 | + /* try to alloc a new handle */ | |
472 | + for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | |
473 | + if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { | |
474 | + DRM_ERROR("Handle 0x%x already in use!\n", handle); | |
475 | + return -EINVAL; | |
476 | + } | |
477 | + | |
478 | + if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { | |
479 | + p->rdev->uvd.filp[i] = p->filp; | |
480 | + p->rdev->uvd.img_size[i] = img_size; | |
481 | + return 0; | |
482 | + } | |
483 | + } | |
484 | + | |
485 | + DRM_ERROR("No more free UVD handles!\n"); | |
486 | + return -EINVAL; | |
487 | + | |
488 | + case 1: | |
489 | + /* it's a decode msg, validate codec and calc buffer sizes */ | |
490 | + r = radeon_uvd_validate_codec(p, msg[4]); | |
491 | + if (!r) | |
492 | + r = radeon_uvd_cs_msg_decode(msg, buf_sizes); | |
493 | + radeon_bo_kunmap(bo); | |
494 | + if (r) | |
495 | + return r; | |
496 | + | |
497 | + /* validate the handle */ | |
498 | + for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | |
499 | + if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { | |
500 | + if (p->rdev->uvd.filp[i] != p->filp) { | |
501 | + DRM_ERROR("UVD handle collision detected!\n"); | |
502 | + return -EINVAL; | |
503 | + } | |
504 | + return 0; | |
505 | + } | |
506 | + } | |
507 | + | |
508 | + DRM_ERROR("Invalid UVD handle 0x%x!\n", handle); | |
509 | + return -ENOENT; | |
510 | + | |
511 | + case 2: | |
449 | 512 | /* it's a destroy msg, free the handle */ |
450 | 513 | for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) |
451 | 514 | atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); |
452 | 515 | radeon_bo_kunmap(bo); |
453 | 516 | return 0; |
454 | - } else { | |
455 | - /* it's a create msg, calc image size (width * height) */ | |
456 | - img_size = msg[7] * msg[8]; | |
457 | - radeon_bo_kunmap(bo); | |
458 | 517 | |
459 | - if (msg_type != 0) { | |
460 | - DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); | |
461 | - return -EINVAL; | |
462 | - } | |
518 | + default: | |
463 | 519 | |
464 | - /* it's a create msg, no special handling needed */ | |
520 | + DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); | |
521 | + return -EINVAL; | |
465 | 522 | } |
466 | 523 | |
467 | - /* create or decode, validate the handle */ | |
468 | - for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | |
469 | - if (atomic_read(&p->rdev->uvd.handles[i]) == handle) | |
470 | - return 0; | |
471 | - } | |
472 | - | |
473 | - /* handle not found try to alloc a new one */ | |
474 | - for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { | |
475 | - if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { | |
476 | - p->rdev->uvd.filp[i] = p->filp; | |
477 | - p->rdev->uvd.img_size[i] = img_size; | |
478 | - return 0; | |
479 | - } | |
480 | - } | |
481 | - | |
482 | - DRM_ERROR("No more free UVD handles!\n"); | |
524 | + BUG(); | |
483 | 525 | return -EINVAL; |
484 | 526 | } |
485 | 527 |
drivers/gpu/drm/radeon/radeon_vce.c
... | ... | @@ -493,18 +493,27 @@ |
493 | 493 | * |
494 | 494 | * @p: parser context |
495 | 495 | * @handle: handle to validate |
496 | + * @allocated: allocated a new handle? | |
496 | 497 | * |
497 | 498 | * Validates the handle and return the found session index or -EINVAL |
498 | 499 | * we we don't have another free session index. |
499 | 500 | */ |
500 | -int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle) | |
501 | +static int radeon_vce_validate_handle(struct radeon_cs_parser *p, | |
502 | + uint32_t handle, bool *allocated) | |
501 | 503 | { |
502 | 504 | unsigned i; |
503 | 505 | |
506 | + *allocated = false; | |
507 | + | |
504 | 508 | /* validate the handle */ |
505 | 509 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { |
506 | - if (atomic_read(&p->rdev->vce.handles[i]) == handle) | |
510 | + if (atomic_read(&p->rdev->vce.handles[i]) == handle) { | |
511 | + if (p->rdev->vce.filp[i] != p->filp) { | |
512 | + DRM_ERROR("VCE handle collision detected!\n"); | |
513 | + return -EINVAL; | |
514 | + } | |
507 | 515 | return i; |
516 | + } | |
508 | 517 | } |
509 | 518 | |
510 | 519 | /* handle not found try to alloc a new one */ |
... | ... | @@ -512,6 +521,7 @@ |
512 | 521 | if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { |
513 | 522 | p->rdev->vce.filp[i] = p->filp; |
514 | 523 | p->rdev->vce.img_size[i] = 0; |
524 | + *allocated = true; | |
515 | 525 | return i; |
516 | 526 | } |
517 | 527 | } |
518 | 528 | |
... | ... | @@ -529,10 +539,10 @@ |
529 | 539 | int radeon_vce_cs_parse(struct radeon_cs_parser *p) |
530 | 540 | { |
531 | 541 | int session_idx = -1; |
532 | - bool destroyed = false; | |
542 | + bool destroyed = false, created = false, allocated = false; | |
533 | 543 | uint32_t tmp, handle = 0; |
534 | 544 | uint32_t *size = &tmp; |
535 | - int i, r; | |
545 | + int i, r = 0; | |
536 | 546 | |
537 | 547 | while (p->idx < p->chunk_ib->length_dw) { |
538 | 548 | uint32_t len = radeon_get_ib_value(p, p->idx); |
539 | 549 | |
540 | 550 | |
... | ... | @@ -540,18 +550,21 @@ |
540 | 550 | |
541 | 551 | if ((len < 8) || (len & 3)) { |
542 | 552 | DRM_ERROR("invalid VCE command length (%d)!\n", len); |
543 | - return -EINVAL; | |
553 | + r = -EINVAL; | |
554 | + goto out; | |
544 | 555 | } |
545 | 556 | |
546 | 557 | if (destroyed) { |
547 | 558 | DRM_ERROR("No other command allowed after destroy!\n"); |
548 | - return -EINVAL; | |
559 | + r = -EINVAL; | |
560 | + goto out; | |
549 | 561 | } |
550 | 562 | |
551 | 563 | switch (cmd) { |
552 | 564 | case 0x00000001: // session |
553 | 565 | handle = radeon_get_ib_value(p, p->idx + 2); |
554 | - session_idx = radeon_vce_validate_handle(p, handle); | |
566 | + session_idx = radeon_vce_validate_handle(p, handle, | |
567 | + &allocated); | |
555 | 568 | if (session_idx < 0) |
556 | 569 | return session_idx; |
557 | 570 | size = &p->rdev->vce.img_size[session_idx]; |
... | ... | @@ -561,6 +574,13 @@ |
561 | 574 | break; |
562 | 575 | |
563 | 576 | case 0x01000001: // create |
577 | + created = true; | |
578 | + if (!allocated) { | |
579 | + DRM_ERROR("Handle already in use!\n"); | |
580 | + r = -EINVAL; | |
581 | + goto out; | |
582 | + } | |
583 | + | |
564 | 584 | *size = radeon_get_ib_value(p, p->idx + 8) * |
565 | 585 | radeon_get_ib_value(p, p->idx + 10) * |
566 | 586 | 8 * 3 / 2; |
567 | 587 | |
... | ... | @@ -578,12 +598,12 @@ |
578 | 598 | r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9, |
579 | 599 | *size); |
580 | 600 | if (r) |
581 | - return r; | |
601 | + goto out; | |
582 | 602 | |
583 | 603 | r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11, |
584 | 604 | *size / 3); |
585 | 605 | if (r) |
586 | - return r; | |
606 | + goto out; | |
587 | 607 | break; |
588 | 608 | |
589 | 609 | case 0x02000001: // destroy |
... | ... | @@ -594,7 +614,7 @@ |
594 | 614 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
595 | 615 | *size * 2); |
596 | 616 | if (r) |
597 | - return r; | |
617 | + goto out; | |
598 | 618 | break; |
599 | 619 | |
600 | 620 | case 0x05000004: // video bitstream buffer |
601 | 621 | |
602 | 622 | |
603 | 623 | |
604 | 624 | |
605 | 625 | |
... | ... | @@ -602,36 +622,47 @@ |
602 | 622 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
603 | 623 | tmp); |
604 | 624 | if (r) |
605 | - return r; | |
625 | + goto out; | |
606 | 626 | break; |
607 | 627 | |
608 | 628 | case 0x05000005: // feedback buffer |
609 | 629 | r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2, |
610 | 630 | 4096); |
611 | 631 | if (r) |
612 | - return r; | |
632 | + goto out; | |
613 | 633 | break; |
614 | 634 | |
615 | 635 | default: |
616 | 636 | DRM_ERROR("invalid VCE command (0x%x)!\n", cmd); |
617 | - return -EINVAL; | |
637 | + r = -EINVAL; | |
638 | + goto out; | |
618 | 639 | } |
619 | 640 | |
620 | 641 | if (session_idx == -1) { |
621 | 642 | DRM_ERROR("no session command at start of IB\n"); |
622 | - return -EINVAL; | |
643 | + r = -EINVAL; | |
644 | + goto out; | |
623 | 645 | } |
624 | 646 | |
625 | 647 | p->idx += len / 4; |
626 | 648 | } |
627 | 649 | |
628 | - if (destroyed) { | |
629 | - /* IB contains a destroy msg, free the handle */ | |
650 | + if (allocated && !created) { | |
651 | + DRM_ERROR("New session without create command!\n"); | |
652 | + r = -ENOENT; | |
653 | + } | |
654 | + | |
655 | +out: | |
656 | + if ((!r && destroyed) || (r && allocated)) { | |
657 | + /* | |
658 | + * IB contains a destroy msg or we have allocated an | |
659 | + * handle and got an error, anyway free the handle | |
660 | + */ | |
630 | 661 | for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) |
631 | 662 | atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); |
632 | 663 | } |
633 | 664 | |
634 | - return 0; | |
665 | + return r; | |
635 | 666 | } |
636 | 667 | |
637 | 668 | /** |
drivers/gpu/drm/radeon/rv770d.h
... | ... | @@ -989,6 +989,9 @@ |
989 | 989 | ((n) & 0x3FFF) << 16) |
990 | 990 | |
991 | 991 | /* UVD */ |
992 | +#define UVD_SEMA_ADDR_LOW 0xef00 | |
993 | +#define UVD_SEMA_ADDR_HIGH 0xef04 | |
994 | +#define UVD_SEMA_CMD 0xef08 | |
992 | 995 | #define UVD_GPCOM_VCPU_CMD 0xef0c |
993 | 996 | #define UVD_GPCOM_VCPU_DATA0 0xef10 |
994 | 997 | #define UVD_GPCOM_VCPU_DATA1 0xef14 |
drivers/gpu/drm/radeon/uvd_v1_0.c
... | ... | @@ -466,18 +466,8 @@ |
466 | 466 | struct radeon_semaphore *semaphore, |
467 | 467 | bool emit_wait) |
468 | 468 | { |
469 | - uint64_t addr = semaphore->gpu_addr; | |
470 | - | |
471 | - radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); | |
472 | - radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); | |
473 | - | |
474 | - radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); | |
475 | - radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); | |
476 | - | |
477 | - radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); | |
478 | - radeon_ring_write(ring, emit_wait ? 1 : 0); | |
479 | - | |
480 | - return true; | |
469 | + /* disable semaphores for UVD V1 hardware */ | |
470 | + return false; | |
481 | 471 | } |
482 | 472 | |
483 | 473 | /** |
drivers/gpu/drm/radeon/uvd_v2_2.c
... | ... | @@ -60,6 +60,35 @@ |
60 | 60 | } |
61 | 61 | |
62 | 62 | /** |
63 | + * uvd_v2_2_semaphore_emit - emit semaphore command | |
64 | + * | |
65 | + * @rdev: radeon_device pointer | |
66 | + * @ring: radeon_ring pointer | |
67 | + * @semaphore: semaphore to emit commands for | |
68 | + * @emit_wait: true if we should emit a wait command | |
69 | + * | |
70 | + * Emit a semaphore command (either wait or signal) to the UVD ring. | |
71 | + */ | |
72 | +bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, | |
73 | + struct radeon_ring *ring, | |
74 | + struct radeon_semaphore *semaphore, | |
75 | + bool emit_wait) | |
76 | +{ | |
77 | + uint64_t addr = semaphore->gpu_addr; | |
78 | + | |
79 | + radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); | |
80 | + radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); | |
81 | + | |
82 | + radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); | |
83 | + radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); | |
84 | + | |
85 | + radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); | |
86 | + radeon_ring_write(ring, emit_wait ? 1 : 0); | |
87 | + | |
88 | + return true; | |
89 | +} | |
90 | + | |
91 | +/** | |
63 | 92 | * uvd_v2_2_resume - memory controller programming |
64 | 93 | * |
65 | 94 | * @rdev: radeon_device pointer |