aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c77
1 files changed, 0 insertions, 77 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 22d7497e6fa..a657e331595 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -40,83 +40,6 @@
40#include <linux/vga_switcheroo.h> 40#include <linux/vga_switcheroo.h>
41#include <linux/slab.h> 41#include <linux/slab.h>
42 42
43/* Really want an OS-independent resettable timer. Would like to have
44 * this loop run for (eg) 3 sec, but have the timer reset every time
45 * the head pointer changes, so that EBUSY only happens if the ring
46 * actually stalls for (eg) 3 seconds.
47 */
48int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
49{
50 drm_i915_private_t *dev_priv = dev->dev_private;
51 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
52 u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
53 u32 last_acthd = I915_READ(acthd_reg);
54 u32 acthd;
55 u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
56 int i;
57
58 trace_i915_ring_wait_begin (dev);
59
60 for (i = 0; i < 100000; i++) {
61 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
62 acthd = I915_READ(acthd_reg);
63 ring->space = ring->head - (ring->tail + 8);
64 if (ring->space < 0)
65 ring->space += ring->Size;
66 if (ring->space >= n) {
67 trace_i915_ring_wait_end (dev);
68 return 0;
69 }
70
71 if (dev->primary->master) {
72 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
73 if (master_priv->sarea_priv)
74 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
75 }
76
77
78 if (ring->head != last_head)
79 i = 0;
80 if (acthd != last_acthd)
81 i = 0;
82
83 last_head = ring->head;
84 last_acthd = acthd;
85 msleep_interruptible(10);
86
87 }
88
89 trace_i915_ring_wait_end (dev);
90 return -EBUSY;
91}
92
93/* As a ringbuffer is only allowed to wrap between instructions, fill
94 * the tail with NOOPs.
95 */
96int i915_wrap_ring(struct drm_device *dev)
97{
98 drm_i915_private_t *dev_priv = dev->dev_private;
99 volatile unsigned int *virt;
100 int rem;
101
102 rem = dev_priv->ring.Size - dev_priv->ring.tail;
103 if (dev_priv->ring.space < rem) {
104 int ret = i915_wait_ring(dev, rem, __func__);
105 if (ret)
106 return ret;
107 }
108 dev_priv->ring.space -= rem;
109
110 virt = (unsigned int *)
111 (dev_priv->ring.virtual_start + dev_priv->ring.tail);
112 rem /= 4;
113 while (rem--)
114 *virt++ = MI_NOOP;
115
116 dev_priv->ring.tail = 0;
117
118 return 0;
119}
120 43
121/** 44/**
122 * Sets up the hardware status page for devices that need a physical address 45 * Sets up the hardware status page for devices that need a physical address