OSDN Git Service

via: Try to improve command-buffer chaining.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Fri, 2 Feb 2007 08:15:44 +0000 (09:15 +0100)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Fri, 2 Feb 2007 08:22:30 +0000 (09:22 +0100)
Bump driver date and patchlevel.

shared-core/via_dma.c
shared-core/via_drm.h
shared-core/via_drv.h

index a08d7d5..0915963 100644 (file)
@@ -299,7 +299,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
                                       cmd->size, dev, 1))) {
                return ret;
        }
-               
+
        vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
        if (vb == NULL) {
                return DRM_ERR(EAGAIN);
@@ -433,70 +433,46 @@ static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
  * modifying the pause address stored in the buffer itself. If
  * the regulator has already paused, restart it.
  */
+
 static int via_hook_segment(drm_via_private_t *dev_priv,
                            uint32_t pause_addr_hi, uint32_t pause_addr_lo,
                            int no_pci_fire)
 {
        int paused, count;
        volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+       uint32_t reader,ptr;
 
+       paused = 0;
        via_flush_write_combine();
-       while(! *(via_get_dma(dev_priv)-1));
        *dev_priv->last_pause_ptr = pause_addr_lo;
        via_flush_write_combine();
-
-       /*
-        * The below statement is inserted to really force the flush.
-        * Not sure it is needed.
-        */
-
-       while(! *dev_priv->last_pause_ptr);
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
+               dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
        dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
-       while(! *dev_priv->last_pause_ptr);
-
 
-       paused = 0;
-       count = 20; 
-
-       while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
-       if ((count <= 8) && (count >= 0)) {
-               uint32_t rgtr, ptr;
-               rgtr = *(dev_priv->hw_addr_ptr);
-               ptr = ((volatile char *)dev_priv->last_pause_ptr -
-                     dev_priv->dma_ptr) + dev_priv->dma_offset +
-                     (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
-               if (rgtr <= ptr) {
-                       DRM_ERROR
-                          ("Command regulator\npaused at count %d, address %x, "
-                           "while current pause address is %x.\n"
-                           "Please mail this message to "
-                           "<unichrome-devel@lists.sourceforge.net>\n", count,
-                           rgtr, ptr);
-               }
+       if ((ptr - reader) <= dev_priv->dma_diff ) {
+               count = 10000000;
+               while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
        }
-               
+
        if (paused && !no_pci_fire) {
-               uint32_t rgtr,ptr;
-               uint32_t ptr_low;
-
-               count = 1000000;
-               while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY)
-                      && count--);
-               
-               rgtr = *(dev_priv->hw_addr_ptr);
-               ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + 
-                       dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-               
-
-               ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ? 
-                       ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
-               if (rgtr <= ptr && rgtr >= ptr_low) {
+               reader = *(dev_priv->hw_addr_ptr);
+               if ((ptr - reader) == dev_priv->dma_diff) {
+
+                       /*
+                        * There is a concern that these writes may stall the PCI bus
+                        * if the GPU is not idle. However, idling the GPU first
+                        * doesn't make a difference.
+                        */
+
                        VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
                        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
                        VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
                        VIA_READ(VIA_REG_TRANSPACE);
-               } 
+               }
        }
+
        return paused;
 }
 
@@ -505,6 +481,9 @@ static int via_hook_segment(drm_via_private_t *dev_priv,
 static int via_wait_idle(drm_via_private_t * dev_priv)
 {
        int count = 10000000;
+
+       while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
+
        while (count-- && (VIA_READ(VIA_REG_STATUS) &
                           (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
                            VIA_3D_ENG_BUSY))) ;
@@ -551,7 +530,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
        uint32_t end_addr, end_addr_lo;
        uint32_t command;
        uint32_t agp_base;
-
+       uint32_t ptr;
+       uint32_t reader;
+       int count;
 
        dev_priv->dma_low = 0;
 
@@ -581,6 +562,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
        DRM_WRITEMEMORYBARRIER();
        VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
        VIA_READ(VIA_REG_TRANSPACE);
+
+       dev_priv->dma_diff = 0;
+
+       count = 10000000;
+       while (!(VIA_READ(0x41c) & 0x80000000) && count--);
+
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+           dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+       /*
+        * This is the difference between where we tell the
+        * command reader to pause and where it actually pauses.
+        * This differs between hw implementation so we need to
+        * detect it.
+        */
+
+       dev_priv->dma_diff = ptr - reader;
 }
 
 static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
@@ -598,20 +597,18 @@ static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
        uint32_t *vb = via_get_dma(dev_priv);
        SetReg2DAGP(0x0C, (0 | (0 << 16)));
        SetReg2DAGP(0x10, 0 | (0 << 16));
-       SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000); 
+       SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
 }
 
-
 static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
 {
        uint32_t agp_base;
        uint32_t pause_addr_lo, pause_addr_hi;
        uint32_t jump_addr_lo, jump_addr_hi;
        volatile uint32_t *last_pause_ptr;
-       uint32_t dma_low_save1, dma_low_save2;
 
        agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       via_align_cmd(dev_priv,  HC_HAGPBpID_JUMP, 0, &jump_addr_hi, 
+       via_align_cmd(dev_priv,  HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
                      &jump_addr_lo, 0);
        
        dev_priv->dma_wrap = dev_priv->dma_low;
@@ -627,38 +624,14 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
        }
 
        via_dummy_bitblt(dev_priv);
-       via_dummy_bitblt(dev_priv); 
-
-       last_pause_ptr =
-           via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
-                                      &pause_addr_lo, 0) -1;
-       via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
-                     &pause_addr_lo, 0);
-
-       *last_pause_ptr = pause_addr_lo;
-       dma_low_save1 = dev_priv->dma_low;
-
-       /*
-        * Now, set a trap that will pause the regulator if it tries to rerun the old
-        * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
-        * and reissues the jump command over PCI, while the regulator has already taken the jump
-        * and actually paused at the current buffer end).
-        * There appears to be no other way to detect this condition, since the hw_addr_pointer
-        * does not seem to get updated immediately when a jump occurs.
-        */
-
-       last_pause_ptr =
-           via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
+       via_dummy_bitblt(dev_priv);
+       last_pause_ptr = via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
                                       &pause_addr_lo, 0) -1;
-       via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, 
+       via_align_cmd(dev_priv,  HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
                      &pause_addr_lo, 0);
        *last_pause_ptr = pause_addr_lo;
 
-       dma_low_save2 = dev_priv->dma_low;
-       dev_priv->dma_low = dma_low_save1;      
        via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
-       dev_priv->dma_low = dma_low_save2;
-       via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
 }
 
 
index 16421d7..88345bd 100644 (file)
  * backwards incompatibilities, (which should be avoided whenever possible).
  */
 
-#define VIA_DRM_DRIVER_DATE            "20061227"
+#define VIA_DRM_DRIVER_DATE            "20070202"
 
 #define VIA_DRM_DRIVER_MAJOR           2
 #define VIA_DRM_DRIVER_MINOR           11
-#define VIA_DRM_DRIVER_PATCHLEVEL      0
+#define VIA_DRM_DRIVER_PATCHLEVEL      1
 #define VIA_DRM_DRIVER_VERSION   (((VIA_DRM_DRIVER_MAJOR) << 16) | (VIA_DRM_DRIVER_MINOR))
 
 #define VIA_NR_SAREA_CLIPRECTS                 8
index 7a8f2c3..42d0c74 100644 (file)
@@ -102,6 +102,7 @@ typedef struct drm_via_private {
 #ifdef VIA_HAVE_DMABLIT
        drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
 #endif
+        uint32_t dma_diff;
 } drm_via_private_t;
 
 enum via_family {