aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-02-05 15:49:57 -0500
committerThomas Gleixner <tglx@linutronix.de>2011-02-05 15:50:05 -0500
commit285c1a2c3a5f84ce1c811ab4cb1f8a17466e1a06 (patch)
tree7eb4aeab927a25b6cc82aef21ffd5a4f4866ae4b /drivers/gpu/drm/i915/intel_ringbuffer.c
parent1fb0ef31f428f345a7c3666f8e7444a563edd537 (diff)
parenta9fe8d5fd52ecd17c3f3970bbcf6b3573f831898 (diff)
Merge branch 'irq/urgent' into irq/core
Reason: Get mainline fixes integrated. Further patches conflict with them Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index f6b9baa6a63..6218fa97aa1 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -34,6 +34,14 @@
34#include "i915_trace.h" 34#include "i915_trace.h"
35#include "intel_drv.h" 35#include "intel_drv.h"
36 36
37static inline int ring_space(struct intel_ring_buffer *ring)
38{
39 int space = (ring->head & HEAD_ADDR) - (ring->tail + 8);
40 if (space < 0)
41 space += ring->size;
42 return space;
43}
44
37static u32 i915_gem_get_seqno(struct drm_device *dev) 45static u32 i915_gem_get_seqno(struct drm_device *dev)
38{ 46{
39 drm_i915_private_t *dev_priv = dev->dev_private; 47 drm_i915_private_t *dev_priv = dev->dev_private;
@@ -204,11 +212,9 @@ static int init_ring_common(struct intel_ring_buffer *ring)
204 if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) 212 if (!drm_core_check_feature(ring->dev, DRIVER_MODESET))
205 i915_kernel_lost_context(ring->dev); 213 i915_kernel_lost_context(ring->dev);
206 else { 214 else {
207 ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; 215 ring->head = I915_READ_HEAD(ring);
208 ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 216 ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
209 ring->space = ring->head - (ring->tail + 8); 217 ring->space = ring_space(ring);
210 if (ring->space < 0)
211 ring->space += ring->size;
212 } 218 }
213 219
214 return 0; 220 return 0;
@@ -921,32 +927,34 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
921 } 927 }
922 928
923 ring->tail = 0; 929 ring->tail = 0;
924 ring->space = ring->head - 8; 930 ring->space = ring_space(ring);
925 931
926 return 0; 932 return 0;
927} 933}
928 934
929int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) 935int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
930{ 936{
931 int reread = 0;
932 struct drm_device *dev = ring->dev; 937 struct drm_device *dev = ring->dev;
933 struct drm_i915_private *dev_priv = dev->dev_private; 938 struct drm_i915_private *dev_priv = dev->dev_private;
934 unsigned long end; 939 unsigned long end;
935 u32 head; 940 u32 head;
936 941
942 /* If the reported head position has wrapped or hasn't advanced,
943 * fallback to the slow and accurate path.
944 */
945 head = intel_read_status_page(ring, 4);
946 if (head > ring->head) {
947 ring->head = head;
948 ring->space = ring_space(ring);
949 if (ring->space >= n)
950 return 0;
951 }
952
937 trace_i915_ring_wait_begin (dev); 953 trace_i915_ring_wait_begin (dev);
938 end = jiffies + 3 * HZ; 954 end = jiffies + 3 * HZ;
939 do { 955 do {
940 /* If the reported head position has wrapped or hasn't advanced, 956 ring->head = I915_READ_HEAD(ring);
941 * fallback to the slow and accurate path. 957 ring->space = ring_space(ring);
942 */
943 head = intel_read_status_page(ring, 4);
944 if (reread)
945 head = I915_READ_HEAD(ring);
946 ring->head = head & HEAD_ADDR;
947 ring->space = ring->head - (ring->tail + 8);
948 if (ring->space < 0)
949 ring->space += ring->size;
950 if (ring->space >= n) { 958 if (ring->space >= n) {
951 trace_i915_ring_wait_end(dev); 959 trace_i915_ring_wait_end(dev);
952 return 0; 960 return 0;
@@ -961,7 +969,6 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
961 msleep(1); 969 msleep(1);
962 if (atomic_read(&dev_priv->mm.wedged)) 970 if (atomic_read(&dev_priv->mm.wedged))
963 return -EAGAIN; 971 return -EAGAIN;
964 reread = 1;
965 } while (!time_after(jiffies, end)); 972 } while (!time_after(jiffies, end));
966 trace_i915_ring_wait_end (dev); 973 trace_i915_ring_wait_end (dev);
967 return -EBUSY; 974 return -EBUSY;
@@ -1292,6 +1299,48 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
1292 return intel_init_ring_buffer(dev, ring); 1299 return intel_init_ring_buffer(dev, ring);
1293} 1300}
1294 1301
1302int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
1303{
1304 drm_i915_private_t *dev_priv = dev->dev_private;
1305 struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
1306
1307 *ring = render_ring;
1308 if (INTEL_INFO(dev)->gen >= 6) {
1309 ring->add_request = gen6_add_request;
1310 ring->irq_get = gen6_render_ring_get_irq;
1311 ring->irq_put = gen6_render_ring_put_irq;
1312 } else if (IS_GEN5(dev)) {
1313 ring->add_request = pc_render_add_request;
1314 ring->get_seqno = pc_render_get_seqno;
1315 }
1316
1317 ring->dev = dev;
1318 INIT_LIST_HEAD(&ring->active_list);
1319 INIT_LIST_HEAD(&ring->request_list);
1320 INIT_LIST_HEAD(&ring->gpu_write_list);
1321
1322 ring->size = size;
1323 ring->effective_size = ring->size;
1324 if (IS_I830(ring->dev))
1325 ring->effective_size -= 128;
1326
1327 ring->map.offset = start;
1328 ring->map.size = size;
1329 ring->map.type = 0;
1330 ring->map.flags = 0;
1331 ring->map.mtrr = 0;
1332
1333 drm_core_ioremap_wc(&ring->map, dev);
1334 if (ring->map.handle == NULL) {
1335 DRM_ERROR("can not ioremap virtual address for"
1336 " ring buffer\n");
1337 return -ENOMEM;
1338 }
1339
1340 ring->virtual_start = (void __force __iomem *)ring->map.handle;
1341 return 0;
1342}
1343
1295int intel_init_bsd_ring_buffer(struct drm_device *dev) 1344int intel_init_bsd_ring_buffer(struct drm_device *dev)
1296{ 1345{
1297 drm_i915_private_t *dev_priv = dev->dev_private; 1346 drm_i915_private_t *dev_priv = dev->dev_private;