diff options
| author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2007-05-08 01:47:41 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@linux.ie> | 2007-05-08 01:47:41 -0400 |
| commit | a0a6dd0b221260be1e3da725e6b49797e5fa7429 (patch) | |
| tree | bdb04b4abb2f940ee2a6bc002a7c2cd551121ed6 | |
| parent | bc07dc7f07a2f2d4d0aa4ffb9597413ad9137d44 (diff) | |
via: Try to improve command-buffer chaining.
Bump driver date and patchlevel.
Signed-off-by: Dave Airlie <airlied@linux.ie>
| -rw-r--r-- | drivers/char/drm/via_dma.c | 107 | ||||
| -rw-r--r-- | drivers/char/drm/via_drv.h | 5 |
2 files changed, 46 insertions, 66 deletions
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index c0539c6299cf..7635e859b879 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c | |||
| @@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS) | |||
| 252 | break; | 252 | break; |
| 253 | case VIA_DMA_INITIALIZED: | 253 | case VIA_DMA_INITIALIZED: |
| 254 | retcode = (dev_priv->ring.virtual_start != NULL) ? | 254 | retcode = (dev_priv->ring.virtual_start != NULL) ? |
| 255 | 0 : DRM_ERR(EFAULT); | 255 | 0 : DRM_ERR(EFAULT); |
| 256 | break; | 256 | break; |
| 257 | default: | 257 | default: |
| 258 | retcode = DRM_ERR(EINVAL); | 258 | retcode = DRM_ERR(EINVAL); |
| @@ -432,56 +432,32 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
| 432 | { | 432 | { |
| 433 | int paused, count; | 433 | int paused, count; |
| 434 | volatile uint32_t *paused_at = dev_priv->last_pause_ptr; | 434 | volatile uint32_t *paused_at = dev_priv->last_pause_ptr; |
| 435 | uint32_t reader,ptr; | ||
| 435 | 436 | ||
| 437 | paused = 0; | ||
| 436 | via_flush_write_combine(); | 438 | via_flush_write_combine(); |
| 437 | while (!*(via_get_dma(dev_priv) - 1)) ; | ||
| 438 | *dev_priv->last_pause_ptr = pause_addr_lo; | 439 | *dev_priv->last_pause_ptr = pause_addr_lo; |
| 439 | via_flush_write_combine(); | 440 | via_flush_write_combine(); |
| 440 | 441 | reader = *(dev_priv->hw_addr_ptr); | |
| 441 | /* | 442 | ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + |
| 442 | * The below statement is inserted to really force the flush. | 443 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; |
| 443 | * Not sure it is needed. | ||
| 444 | */ | ||
| 445 | |||
| 446 | while (!*dev_priv->last_pause_ptr) ; | ||
| 447 | dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; | 444 | dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; |
| 448 | while (!*dev_priv->last_pause_ptr) ; | ||
| 449 | 445 | ||
| 450 | paused = 0; | 446 | if ((ptr - reader) <= dev_priv->dma_diff ) { |
| 451 | count = 20; | 447 | count = 10000000; |
| 452 | 448 | while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--); | |
| 453 | while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ; | ||
| 454 | if ((count <= 8) && (count >= 0)) { | ||
| 455 | uint32_t rgtr, ptr; | ||
| 456 | rgtr = *(dev_priv->hw_addr_ptr); | ||
| 457 | ptr = ((volatile char *)dev_priv->last_pause_ptr - | ||
| 458 | dev_priv->dma_ptr) + dev_priv->dma_offset + | ||
| 459 | (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE; | ||
| 460 | if (rgtr <= ptr) { | ||
| 461 | DRM_ERROR | ||
| 462 | ("Command regulator\npaused at count %d, address %x, " | ||
| 463 | "while current pause address is %x.\n" | ||
| 464 | "Please mail this message to " | ||
| 465 | "<unichrome-devel@lists.sourceforge.net>\n", count, | ||
| 466 | rgtr, ptr); | ||
| 467 | } | ||
| 468 | } | 449 | } |
| 469 | 450 | ||
| 470 | if (paused && !no_pci_fire) { | 451 | if (paused && !no_pci_fire) { |
| 471 | uint32_t rgtr, ptr; | 452 | reader = *(dev_priv->hw_addr_ptr); |
| 472 | uint32_t ptr_low; | 453 | if ((ptr - reader) == dev_priv->dma_diff) { |
| 473 | 454 | ||
| 474 | count = 1000000; | 455 | /* |
| 475 | while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) | 456 | * There is a concern that these writes may stall the PCI bus |
| 476 | && count--) ; | 457 | * if the GPU is not idle. However, idling the GPU first |
| 458 | * doesn't make a difference. | ||
| 459 | */ | ||
| 477 | 460 | ||
| 478 | rgtr = *(dev_priv->hw_addr_ptr); | ||
| 479 | ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + | ||
| 480 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; | ||
| 481 | |||
| 482 | ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ? | ||
| 483 | ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0; | ||
| 484 | if (rgtr <= ptr && rgtr >= ptr_low) { | ||
| 485 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | 461 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); |
| 486 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); | 462 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); |
| 487 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); | 463 | VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); |
| @@ -494,6 +470,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
| 494 | static int via_wait_idle(drm_via_private_t * dev_priv) | 470 | static int via_wait_idle(drm_via_private_t * dev_priv) |
| 495 | { | 471 | { |
| 496 | int count = 10000000; | 472 | int count = 10000000; |
| 473 | |||
| 474 | while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--); | ||
| 475 | |||
| 497 | while (count-- && (VIA_READ(VIA_REG_STATUS) & | 476 | while (count-- && (VIA_READ(VIA_REG_STATUS) & |
| 498 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | | 477 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | |
| 499 | VIA_3D_ENG_BUSY))) ; | 478 | VIA_3D_ENG_BUSY))) ; |
| @@ -537,6 +516,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
| 537 | uint32_t end_addr, end_addr_lo; | 516 | uint32_t end_addr, end_addr_lo; |
| 538 | uint32_t command; | 517 | uint32_t command; |
| 539 | uint32_t agp_base; | 518 | uint32_t agp_base; |
| 519 | uint32_t ptr; | ||
| 520 | uint32_t reader; | ||
| 521 | int count; | ||
| 540 | 522 | ||
| 541 | dev_priv->dma_low = 0; | 523 | dev_priv->dma_low = 0; |
| 542 | 524 | ||
| @@ -554,7 +536,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
| 554 | &pause_addr_hi, &pause_addr_lo, 1) - 1; | 536 | &pause_addr_hi, &pause_addr_lo, 1) - 1; |
| 555 | 537 | ||
| 556 | via_flush_write_combine(); | 538 | via_flush_write_combine(); |
| 557 | while (!*dev_priv->last_pause_ptr) ; | 539 | while(! *dev_priv->last_pause_ptr); |
| 558 | 540 | ||
| 559 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); | 541 | VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); |
| 560 | VIA_WRITE(VIA_REG_TRANSPACE, command); | 542 | VIA_WRITE(VIA_REG_TRANSPACE, command); |
| @@ -566,6 +548,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) | |||
| 566 | DRM_WRITEMEMORYBARRIER(); | 548 | DRM_WRITEMEMORYBARRIER(); |
| 567 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); | 549 | VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); |
| 568 | VIA_READ(VIA_REG_TRANSPACE); | 550 | VIA_READ(VIA_REG_TRANSPACE); |
| 551 | |||
| 552 | dev_priv->dma_diff = 0; | ||
| 553 | |||
| 554 | count = 10000000; | ||
| 555 | while (!(VIA_READ(0x41c) & 0x80000000) && count--); | ||
| 556 | |||
| 557 | reader = *(dev_priv->hw_addr_ptr); | ||
| 558 | ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + | ||
| 559 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; | ||
| 560 | |||
| 561 | /* | ||
| 562 | * This is the difference between where we tell the | ||
| 563 | * command reader to pause and where it actually pauses. | ||
| 564 | * This differs between hw implementation so we need to | ||
| 565 | * detect it. | ||
| 566 | */ | ||
| 567 | |||
| 568 | dev_priv->dma_diff = ptr - reader; | ||
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) | 571 | static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) |
| @@ -592,7 +592,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) | |||
| 592 | uint32_t pause_addr_lo, pause_addr_hi; | 592 | uint32_t pause_addr_lo, pause_addr_hi; |
| 593 | uint32_t jump_addr_lo, jump_addr_hi; | 593 | uint32_t jump_addr_lo, jump_addr_hi; |
| 594 | volatile uint32_t *last_pause_ptr; | 594 | volatile uint32_t *last_pause_ptr; |
| 595 | uint32_t dma_low_save1, dma_low_save2; | ||
| 596 | 595 | ||
| 597 | agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; | 596 | agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; |
| 598 | via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, | 597 | via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, |
| @@ -619,31 +618,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) | |||
| 619 | &pause_addr_lo, 0); | 618 | &pause_addr_lo, 0); |
| 620 | 619 | ||
| 621 | *last_pause_ptr = pause_addr_lo; | 620 | *last_pause_ptr = pause_addr_lo; |
| 622 | dma_low_save1 = dev_priv->dma_low; | ||
| 623 | |||
| 624 | /* | ||
| 625 | * Now, set a trap that will pause the regulator if it tries to rerun the old | ||
| 626 | * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause | ||
| 627 | * and reissues the jump command over PCI, while the regulator has already taken the jump | ||
| 628 | * and actually paused at the current buffer end). | ||
| 629 | * There appears to be no other way to detect this condition, since the hw_addr_pointer | ||
| 630 | * does not seem to get updated immediately when a jump occurs. | ||
| 631 | */ | ||
| 632 | 621 | ||
| 633 | last_pause_ptr = | 622 | via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0); |
| 634 | via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, | ||
| 635 | &pause_addr_lo, 0) - 1; | ||
| 636 | via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, | ||
| 637 | &pause_addr_lo, 0); | ||
| 638 | *last_pause_ptr = pause_addr_lo; | ||
| 639 | |||
| 640 | dma_low_save2 = dev_priv->dma_low; | ||
| 641 | dev_priv->dma_low = dma_low_save1; | ||
| 642 | via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); | ||
| 643 | dev_priv->dma_low = dma_low_save2; | ||
| 644 | via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); | ||
| 645 | } | 623 | } |
| 646 | 624 | ||
| 625 | |||
| 647 | static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) | 626 | static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) |
| 648 | { | 627 | { |
| 649 | via_cmdbuf_jump(dev_priv); | 628 | via_cmdbuf_jump(dev_priv); |
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 8b8778d4a423..b46ca8e6306d 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
| @@ -29,11 +29,11 @@ | |||
| 29 | 29 | ||
| 30 | #define DRIVER_NAME "via" | 30 | #define DRIVER_NAME "via" |
| 31 | #define DRIVER_DESC "VIA Unichrome / Pro" | 31 | #define DRIVER_DESC "VIA Unichrome / Pro" |
| 32 | #define DRIVER_DATE "20061227" | 32 | #define DRIVER_DATE "20070202" |
| 33 | 33 | ||
| 34 | #define DRIVER_MAJOR 2 | 34 | #define DRIVER_MAJOR 2 |
| 35 | #define DRIVER_MINOR 11 | 35 | #define DRIVER_MINOR 11 |
| 36 | #define DRIVER_PATCHLEVEL 0 | 36 | #define DRIVER_PATCHLEVEL 1 |
| 37 | 37 | ||
| 38 | #include "via_verifier.h" | 38 | #include "via_verifier.h" |
| 39 | 39 | ||
| @@ -93,6 +93,7 @@ typedef struct drm_via_private { | |||
| 93 | unsigned long vram_offset; | 93 | unsigned long vram_offset; |
| 94 | unsigned long agp_offset; | 94 | unsigned long agp_offset; |
| 95 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; | 95 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; |
| 96 | uint32_t dma_diff; | ||
| 96 | } drm_via_private_t; | 97 | } drm_via_private_t; |
| 97 | 98 | ||
| 98 | enum via_family { | 99 | enum via_family { |
