diff options
author | Thomas Hellstrom <thomas-at-shipmail-dot-org> | 2009-03-11 09:03:47 +0100 |
---|---|---|
committer | Thomas Hellstrom <thomas-at-shipmail-dot-org> | 2009-03-11 09:03:47 +0100 |
commit | 649b5f84710cc2da0e51870a9e5749a1ba47a3d3 (patch) | |
tree | 7ff813ba7767f3c833bec242e8f2485a9ecbf015 | |
parent | a5c936345b0d37ad0c4030bf5d56722f71986b31 (diff) |
openchrome: Fix a performance regression.
Unichrome's don't like small command submissions, so pad the
command stream with dummy data.
Also use 0x40c as pause address register instead of 0x418, as
reading the latter seems to sometimes stall the PCI bus until
the AGP command reader has completed a cycle.
-rw-r--r-- | linux-core/openchrome/via_dma.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/linux-core/openchrome/via_dma.c b/linux-core/openchrome/via_dma.c index e0b8baab..87f129b1 100644 --- a/linux-core/openchrome/via_dma.c +++ b/linux-core/openchrome/via_dma.c @@ -41,6 +41,7 @@ #include "via_3d_reg.h" #define VIA_FENCE_EXTRA (7*8) +#define VIA_PAD_SUBMISSION_SIZE (0x102) #define VIA_OUT_RING_H1(nReg, nData) \ { \ @@ -174,7 +175,7 @@ void via_dma_initialize(struct drm_via_private *dev_priv) dev_priv->dma_offset = dev_priv->agpc_bo->offset; dev_priv->last_pause_ptr = NULL; dev_priv->hw_addr_ptr = - (uint32_t __iomem *) (dev_priv->mmio_map + 0x418); + (uint32_t __iomem *) (dev_priv->mmio_map + 0x40c); via_cmdbuf_start(dev_priv); } @@ -587,7 +588,12 @@ int via_copy_cmdbuf(struct drm_via_private *dev_priv, } if (mechanism == _VIA_MECHANISM_AGP && drm_via_disable_verifier) { - vb = via_check_dma(dev_priv, size + VIA_FENCE_EXTRA); + uint32_t check_size = size + VIA_FENCE_EXTRA; + + if (check_size < VIA_PAD_SUBMISSION_SIZE) + check_size = VIA_PAD_SUBMISSION_SIZE; + + vb = via_check_dma(dev_priv, check_size); if (unlikely(!vb)) { DRM_ERROR("No space in AGP ring buffer.\n"); return -EBUSY; @@ -608,6 +614,20 @@ int via_copy_cmdbuf(struct drm_via_private *dev_priv, return 0; } +static void via_pad_submission(struct drm_via_private *dev_priv, int qwords) +{ + uint32_t *vb; + + if (unlikely(qwords == 0)) + return; + vb = via_get_dma(dev_priv); + VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16); + if (unlikely(qwords == 1)) + return; + via_align_buffer(dev_priv, vb, qwords); +} + + int via_dispatch_commands(struct drm_device *dev, unsigned long size, uint32_t mechanism, bool emit_seq) { @@ -619,7 +639,13 @@ int via_dispatch_commands(struct drm_device *dev, unsigned long size, switch (mechanism) { case _VIA_MECHANISM_AGP: if (!drm_via_disable_verifier) { - vb = via_check_dma(dev_priv, size + VIA_FENCE_EXTRA); + unsigned long check_size = + size + VIA_FENCE_EXTRA; + + if (check_size < VIA_PAD_SUBMISSION_SIZE) + check_size = VIA_PAD_SUBMISSION_SIZE; + + vb = via_check_dma(dev_priv, check_size); if (unlikely(!vb)) { DRM_ERROR("No space in AGP ring buffer.\n"); return -EBUSY; @@ -633,7 +659,12 @@ int via_dispatch_commands(struct drm_device *dev, unsigned long size, if (emit_seq || !via_no_tracker(dev_priv)) { via_emit_fence_seq(dev_priv, VIA_FENCE_OFFSET_CMD, seq); via_add_tracker(dev_priv, seq); + size += VIA_FENCE_EXTRA; } + + if (size < VIA_PAD_SUBMISSION_SIZE) + via_pad_submission(dev_priv, (VIA_PAD_SUBMISSION_SIZE - size) >> 3); + via_cmdbuf_pause(dev_priv); return 0; case _VIA_MECHANISM_PCI: |