summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2009-11-23 21:19:44 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2009-11-23 21:19:44 +0000
commit4f825d96668fa96dcf469957b5a0bf14e02a8d09 (patch)
tree208c735ef6cd50833b69af9b769f45522db0f336 /sys/dev/pci
parent62aebd64581a11f2c5857326e0d46370b52e1685 (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.c1
-rw-r--r--sys/dev/pci/drm/i915_drv.c39
-rw-r--r--sys/dev/pci/drm/i915_drv.h3
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 {