diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-11-23 21:19:44 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-11-23 21:19:44 +0000 |
commit | 4f825d96668fa96dcf469957b5a0bf14e02a8d09 (patch) | |
tree | 208c735ef6cd50833b69af9b769f45522db0f336 /sys/dev/pci | |
parent | 62aebd64581a11f2c5857326e0d46370b52e1685 (diff) |
Pad the ringbuffer with NOOPs before wrapping around, instead of
wrapping our commands over.
The documentation says that wrap must not happen in the middle of
commands. and upstream have seen some odd bugs that may be attributed to
this.
Based on a diff by Chris Wilson (ickle) from Intel to the linux driver.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/drm/i915_dma.c | 1 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.c | 39 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.h | 3 |
3 files changed, 31 insertions, 12 deletions
diff --git a/sys/dev/pci/drm/i915_dma.c b/sys/dev/pci/drm/i915_dma.c index bf6694256f0..4e79f63ea4e 100644 --- a/sys/dev/pci/drm/i915_dma.c +++ b/sys/dev/pci/drm/i915_dma.c @@ -117,7 +117,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) } dev_priv->ring.size = init->ring_size; - dev_priv->ring.tail_mask = dev_priv->ring.size - 1; if ((ret = bus_space_map(dev_priv->bst, init->ring_start, init->ring_size, 0, &dev_priv->ring.bsh)) != 0) { diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c index 7e8ab1d0636..5dbe9bf574c 100644 --- a/sys/dev/pci/drm/i915_drv.c +++ b/sys/dev/pci/drm/i915_drv.c @@ -41,6 +41,8 @@ int inteldrm_detach(struct device *, int); int inteldrm_ioctl(struct drm_device *, u_long, caddr_t, struct drm_file *); int inteldrm_activate(struct device *, int); +void inteldrm_wrap_ring(struct drm_i915_private *); + /* For reset and suspend */ int inteldrm_save_state(struct drm_i915_private *); int inteldrm_restore_state(struct drm_i915_private *); @@ -342,13 +344,35 @@ inteldrm_wait_ring(struct drm_i915_private *dev_priv, int n) } void +inteldrm_wrap_ring(struct drm_i915_private *dev_priv) +{ + u_int32_t rem;; + + rem = dev_priv->ring.size - dev_priv->ring.tail; + if (dev_priv->ring.space < rem && + inteldrm_wait_ring(dev_priv, rem) != 0) + return; /* XXX */ + + bus_space_set_region_4(dev_priv->bst, dev_priv->ring.bsh, + dev_priv->ring.woffset, MI_NOOP, rem / 4); + + dev_priv->ring.tail = 0; +} + +void inteldrm_begin_ring(struct drm_i915_private *dev_priv, int ncmd) { + int bytes = 4 * ncmd; + INTELDRM_VPRINTF("%s: %d\n", __func__, ncmd); - if (dev_priv->ring.space < ncmd * 4) - inteldrm_wait_ring(dev_priv, ncmd * 4); - dev_priv->ring.wspace = 0; + if (dev_priv->ring.tail + bytes > dev_priv->ring.size) + inteldrm_wrap_ring(dev_priv); + if (dev_priv->ring.space < bytes) + inteldrm_wait_ring(dev_priv, bytes); dev_priv->ring.woffset = dev_priv->ring.tail; + dev_priv->ring.tail += bytes; + dev_priv->ring.tail &= dev_priv->ring.size - 1; + dev_priv->ring.space -= bytes; } void @@ -357,10 +381,11 @@ inteldrm_out_ring(struct drm_i915_private *dev_priv, u_int32_t cmd) INTELDRM_VPRINTF("%s: %x\n", __func__, cmd); bus_space_write_4(dev_priv->bst, dev_priv->ring.bsh, dev_priv->ring.woffset, cmd); - dev_priv->ring.wspace++; - /* deal with ring wrapping */ + /* + * don't need to deal with wrap here because we padded + * the ring out if we would wrap + */ dev_priv->ring.woffset += 4; - dev_priv->ring.woffset &= dev_priv->ring.tail_mask; } void @@ -368,8 +393,6 @@ inteldrm_advance_ring(struct drm_i915_private *dev_priv) { INTELDRM_VPRINTF("%s: %x, %x\n", __func__, dev_priv->ring.wspace, dev_priv->ring.woffset); - dev_priv->ring.tail = dev_priv->ring.woffset; - dev_priv->ring.space -= dev_priv->ring.wspace * 4; I915_WRITE(PRB0_TAIL, dev_priv->ring.woffset); } diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h index 30e8c6d99b3..eb1bf7ecaa7 100644 --- a/sys/dev/pci/drm/i915_drv.h +++ b/sys/dev/pci/drm/i915_drv.h @@ -59,15 +59,12 @@ enum pipe { #define DRIVER_PATCHLEVEL 0 struct inteldrm_ring { - u_int32_t *kva; bus_space_handle_t bsh; bus_size_t size; u_int32_t head; u_int32_t space; u_int32_t tail; - u_int32_t tail_mask; u_int32_t woffset; - u_int32_t wspace; }; typedef struct drm_i915_private { |