diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/r300_cmdbuf.c | 80 |
1 files changed, 64 insertions, 16 deletions
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 4b3bd6303daf..b1fdfc61f27d 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c | |||
| @@ -577,22 +577,23 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | |||
| 577 | return 0; | 577 | return 0; |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | 580 | static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv, |
| 581 | drm_radeon_kcmd_buffer_t *cmdbuf) | 581 | drm_radeon_kcmd_buffer_t *cmdbuf) |
| 582 | { | 582 | { |
| 583 | u32 *cmd = (u32 *) cmdbuf->buf; | 583 | u32 *cmd; |
| 584 | int count, ret; | 584 | int count; |
| 585 | int expected_count; | ||
| 585 | RING_LOCALS; | 586 | RING_LOCALS; |
| 586 | 587 | ||
| 587 | count=(cmd[0]>>16) & 0x3fff; | 588 | cmd = (u32 *) cmdbuf->buf; |
| 589 | count = (cmd[0]>>16) & 0x3fff; | ||
| 590 | expected_count = cmd[1] >> 16; | ||
| 591 | if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit)) | ||
| 592 | expected_count = (expected_count+1)/2; | ||
| 588 | 593 | ||
| 589 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | 594 | if (count && count != expected_count) { |
| 590 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | 595 | DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n", |
| 591 | return -EINVAL; | 596 | count, expected_count); |
| 592 | } | ||
| 593 | ret = !radeon_check_offset(dev_priv, cmd[2]); | ||
| 594 | if (ret) { | ||
| 595 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
| 596 | return -EINVAL; | 597 | return -EINVAL; |
| 597 | } | 598 | } |
| 598 | 599 | ||
| @@ -604,6 +605,50 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | |||
| 604 | cmdbuf->buf += (count+2)*4; | 605 | cmdbuf->buf += (count+2)*4; |
| 605 | cmdbuf->bufsz -= (count+2)*4; | 606 | cmdbuf->bufsz -= (count+2)*4; |
| 606 | 607 | ||
| 608 | if (!count) { | ||
| 609 | drm_r300_cmd_header_t header; | ||
| 610 | |||
| 611 | if (cmdbuf->bufsz < 4*4 + sizeof(header)) { | ||
| 612 | DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n"); | ||
| 613 | return -EINVAL; | ||
| 614 | } | ||
| 615 | |||
| 616 | header.u = *(unsigned int *)cmdbuf->buf; | ||
| 617 | |||
| 618 | cmdbuf->buf += sizeof(header); | ||
| 619 | cmdbuf->bufsz -= sizeof(header); | ||
| 620 | cmd = (u32 *) cmdbuf->buf; | ||
| 621 | |||
| 622 | if (header.header.cmd_type != R300_CMD_PACKET3 || | ||
| 623 | header.packet3.packet != R300_CMD_PACKET3_RAW || | ||
| 624 | cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) { | ||
| 625 | DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n"); | ||
| 626 | return -EINVAL; | ||
| 627 | } | ||
| 628 | |||
| 629 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
| 630 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
| 631 | return -EINVAL; | ||
| 632 | } | ||
| 633 | if (!radeon_check_offset(dev_priv, cmd[2])) { | ||
| 634 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
| 635 | return -EINVAL; | ||
| 636 | } | ||
| 637 | if (cmd[3] != expected_count) { | ||
| 638 | DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n", | ||
| 639 | cmd[3], expected_count); | ||
| 640 | return -EINVAL; | ||
| 641 | } | ||
| 642 | |||
| 643 | BEGIN_RING(4); | ||
| 644 | OUT_RING(cmd[0]); | ||
| 645 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3); | ||
| 646 | ADVANCE_RING(); | ||
| 647 | |||
| 648 | cmdbuf->buf += 4*4; | ||
| 649 | cmdbuf->bufsz -= 4*4; | ||
| 650 | } | ||
| 651 | |||
| 607 | return 0; | 652 | return 0; |
| 608 | } | 653 | } |
| 609 | 654 | ||
| @@ -648,18 +693,21 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | |||
| 648 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); | 693 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); |
| 649 | 694 | ||
| 650 | case RADEON_CP_INDX_BUFFER: | 695 | case RADEON_CP_INDX_BUFFER: |
| 651 | /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | 696 | DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n"); |
| 652 | return r300_emit_indx_buffer(dev_priv, cmdbuf); | 697 | return -EINVAL; |
| 653 | case RADEON_CP_3D_DRAW_IMMD_2: | 698 | case RADEON_CP_3D_DRAW_IMMD_2: |
| 654 | /* triggers drawing using in-packet vertex data */ | 699 | /* triggers drawing using in-packet vertex data */ |
| 655 | case RADEON_CP_3D_DRAW_VBUF_2: | 700 | case RADEON_CP_3D_DRAW_VBUF_2: |
| 656 | /* triggers drawing of vertex buffers setup elsewhere */ | 701 | /* triggers drawing of vertex buffers setup elsewhere */ |
| 702 | dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | | ||
| 703 | RADEON_PURGE_EMITED); | ||
| 704 | break; | ||
| 657 | case RADEON_CP_3D_DRAW_INDX_2: | 705 | case RADEON_CP_3D_DRAW_INDX_2: |
| 658 | /* triggers drawing using indices to vertex buffer */ | 706 | /* triggers drawing using indices to vertex buffer */ |
| 659 | /* whenever we send vertex we clear flush & purge */ | 707 | /* whenever we send vertex we clear flush & purge */ |
| 660 | dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | | 708 | dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | |
| 661 | RADEON_PURGE_EMITED); | 709 | RADEON_PURGE_EMITED); |
| 662 | break; | 710 | return r300_emit_draw_indx_2(dev_priv, cmdbuf); |
| 663 | case RADEON_WAIT_FOR_IDLE: | 711 | case RADEON_WAIT_FOR_IDLE: |
| 664 | case RADEON_CP_NOP: | 712 | case RADEON_CP_NOP: |
| 665 | /* these packets are safe */ | 713 | /* these packets are safe */ |
| @@ -757,7 +805,7 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) | |||
| 757 | { | 805 | { |
| 758 | uint32_t cache_z, cache_3d, cache_2d; | 806 | uint32_t cache_z, cache_3d, cache_2d; |
| 759 | RING_LOCALS; | 807 | RING_LOCALS; |
| 760 | 808 | ||
| 761 | cache_z = R300_ZC_FLUSH; | 809 | cache_z = R300_ZC_FLUSH; |
| 762 | cache_2d = R300_RB2D_DC_FLUSH; | 810 | cache_2d = R300_RB2D_DC_FLUSH; |
| 763 | cache_3d = R300_RB3D_DC_FLUSH; | 811 | cache_3d = R300_RB3D_DC_FLUSH; |
