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); }