aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2007-05-08 01:47:41 -0400
committerDave Airlie <airlied@linux.ie>2007-05-08 01:47:41 -0400
commita0a6dd0b221260be1e3da725e6b49797e5fa7429 (patch)
treebdb04b4abb2f940ee2a6bc002a7c2cd551121ed6
parentbc07dc7f07a2f2d4d0aa4ffb9597413ad9137d44 (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.c107
-rw-r--r--drivers/char/drm/via_drv.h5
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,
494static int via_wait_idle(drm_via_private_t * dev_priv) 470static 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
571static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) 571static 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
647static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) 626static 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
98enum via_family { 99enum via_family {