Hi

While trying to make googleearth work on a Via Epia LN board with
openchrome and GL we noticed that the X server crashed after about
30 seconds of use.  I got a flood of the following messages.

Oct 26 12:13:24 test kernel: error: [drm:pid97391:via_hook_segment] *ERROR* 
Paused at incorrect address. 0xe1fcf300, 0xe1fc4900 0x00000000
Oct 26 12:13:24 test kernel: error: [drm:pid97391:via_hook_segment] *ERROR* 
Paused at incorrect address. 0xe1fd0300, 0xe1fc4900 0x00000000
Oct 26 12:13:24 test kernel: error: [drm:pid97391:via_cmdbuf_size] *ERROR* 
VIA_CMDBUF_LAG timed out.

Some research showed that occasionally the GPU pauses and when the
pipe is restarted, commands are reordered and the next command after
the paused command is dropped.

I located a patch which I hand applied because every chunk failed.
It has fixed the stability issue and gpu pipe restarting issue.

I still have a problem with googleearth only displaying its image
in part of the window.  It looks like the plane size is correct but
it gets the offset wrong so there is a blank on the right side the
size of the left menu pane and a blank at the bottom the size of
the window bar and menu bar at the top of the window.

Do you have any ideas how to fix this?

Ian

-- 
Ian Freislich

Index: sys/dev/drm/via_dma.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/drm/via_dma.c,v
retrieving revision 1.2
diff -u -d -r1.2 via_dma.c
--- sys/dev/drm/via_dma.c       22 Apr 2010 18:21:25 -0000      1.2
+++ sys/dev/drm/via_dma.c       26 Oct 2010 15:03:04 -0000
@@ -119,10 +119,12 @@
        uint32_t count;
        hw_addr_ptr = dev_priv->hw_addr_ptr;
        cur_addr = dev_priv->dma_low;
-       next_addr = cur_addr + size + 512 * 1024;
+       next_addr = cur_addr + size + 64 * 1024;
        count = 1000000;
        do {
-               hw_addr = *hw_addr_ptr - agp_base;
+               (void) *hw_addr_ptr;
+               DRM_MEMORYBARRIER();
+               hw_addr = (*hw_addr_ptr - agp_base);
                if (count-- == 0) {
                        DRM_ERROR
                            ("via_cmdbuf_wait timed out hw %x cur_addr %x 
next_addr %x\n",
@@ -272,7 +274,9 @@
 {
        drm_via_private_t *dev_priv;
        uint32_t *vb;
+#if 0
        int ret;
+#endif
 
        dev_priv = (drm_via_private_t *) dev->dev_private;
 
@@ -285,7 +289,12 @@
                return -ENOMEM;
        }
 
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+       vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
+       if (vb == NULL) {
+               return -EAGAIN;
+       }
+
+       if (DRM_COPY_FROM_USER(vb, cmd->buf, cmd->size))
                return -EFAULT;
 
        /*
@@ -294,19 +303,15 @@
         * copy it to AGP memory when ready.
         */
 
+#if 0
        if ((ret =
             via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
                                       cmd->size, dev, 1))) {
                return ret;
        }
 
-       vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
-       if (vb == NULL) {
-               return -EAGAIN;
-       }
-
        memcpy(vb, dev_priv->pci_buf, cmd->size);
-
+#endif
        dev_priv->dma_low += cmd->size;
 
        /*
@@ -467,11 +472,28 @@
                reader = *(dev_priv->hw_addr_ptr);
                diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
                diff &= (dev_priv->dma_high - 1);
-               if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
-                       DRM_ERROR("Paused at incorrect address. "
-                                 "0x%08x, 0x%08x 0x%08x\n",
-                                 ptr, reader, dev_priv->dma_diff);
-               } else if (diff == 0) {
+               if (diff < (dev_priv->dma_high >> 1)) {
+                       if (diff != 0) {
+                               volatile uint32_t *rekick;
+
+                               DRM_INFO("Paused at incorrect address. "
+                                   "0x%08x, 0x%08x 0x%08x. Restarting.\n",
+                                   ptr, reader, dev_priv->dma_diff);
+
+                               /*
+                                * Obtain the new pause address the command
+                                * reader was supposed to pick up.
+                                */
+
+                               rekick = (volatile uint32_t *)
+                                  dev_priv->dma_ptr +
+                                  ((reader - dev_priv->dma_offset -
+                                  (uint32_t) dev_priv->agpAddr +
+                                  dev_priv->dma_diff - 4) >> 2);
+                               pause_addr_lo = *rekick;
+                               pause_addr_hi = *(--rekick);
+                       }
+
                        /*
                         * There is a concern that these writes may stall the 
PCI bus
                         * if the GPU is not idle. However, idling the GPU first
@@ -612,13 +634,16 @@
 {
        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 jump_addr_lo, jump_addr_hi, hook_addr;
+       volatile uint32_t *hook_ptr;
        uint32_t dma_low_save1, dma_low_save2;
 
        agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       hook_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
+                                &jump_addr_hi, &jump_addr_lo, 0);
        via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
-                     &jump_addr_lo, 0);
+                     &hook_addr, 0);
+       *(--hook_ptr) = hook_addr;
 
        dev_priv->dma_wrap = dev_priv->dma_low;
 
@@ -634,13 +659,13 @@
        via_dummy_bitblt(dev_priv);
        via_dummy_bitblt(dev_priv);
 
-       last_pause_ptr =
+       hook_ptr =
            via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                         &pause_addr_lo, 0) - 1;
+                         &pause_addr_lo, 0);
        via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
                      &pause_addr_lo, 0);
 
-       *last_pause_ptr = pause_addr_lo;
+       *(--hook_ptr) = pause_addr_lo;
        dma_low_save1 = dev_priv->dma_low;
 
        /*
@@ -652,12 +677,12 @@
         * does not seem to get updated immediately when a jump occurs.
         */
 
-       last_pause_ptr =
+       hook_ptr =
                via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                             &pause_addr_lo, 0) - 1;
+                             &pause_addr_lo, 0);
        via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
                      &pause_addr_lo, 0);
-       *last_pause_ptr = pause_addr_lo;
+       *(--hook_ptr) = pause_addr_lo;
 
        dma_low_save2 = dev_priv->dma_low;
        dev_priv->dma_low = dma_low_save1;
@@ -674,9 +699,16 @@
 
 static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
 {
-       uint32_t pause_addr_lo, pause_addr_hi;
+       uint32_t pause_addr_lo, pause_addr_hi, hook;
+       volatile uint32_t *hook_addr;
 
-       via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
+       hook_addr = via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, 
&pause_addr_lo, 0);
+#if 1
+       if (cmd_type == HC_HAGPBpID_PAUSE) {
+               via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &hook, 0);
+               *(--hook_addr) = hook;
+       }
+#endif
        via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
 }
 
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to