drm/i915/ringbuffer: Use the HEAD auto-reporting mechanism
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_ringbuffer.c
index e88214e..390aa21 100644 (file)
@@ -174,7 +174,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
 
        I915_WRITE_CTL(ring,
                        ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES)
-                       | RING_NO_REPORT | RING_VALID);
+                       | RING_REPORT_64K | RING_VALID);
 
        /* If the head is still not zero, the ring is dead */
        if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||
@@ -547,7 +547,7 @@ static int init_status_page(struct intel_ring_buffer *ring)
        obj_priv = to_intel_bo(obj);
        obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
 
-       ret = i915_gem_object_pin(obj, 4096, true);
+       ret = i915_gem_object_pin(obj, 4096, true, false);
        if (ret != 0) {
                goto err_unref;
        }
@@ -578,7 +578,6 @@ err:
 int intel_init_ring_buffer(struct drm_device *dev,
                           struct intel_ring_buffer *ring)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj_priv;
        struct drm_gem_object *obj;
        int ret;
@@ -603,7 +602,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
 
        ring->gem_object = obj;
 
-       ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
+       ret = i915_gem_object_pin(obj, PAGE_SIZE, true, false);
        if (ret)
                goto err_unref;
 
@@ -626,16 +625,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
        if (ret)
                goto err_unmap;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               i915_kernel_lost_context(dev);
-       else {
-               ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
-               ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->size;
-       }
-       return ret;
+       return 0;
 
 err_unmap:
        drm_core_ioremapfree(&ring->map, dev);
@@ -651,9 +641,17 @@ err_hws:
 
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 {
+       struct drm_i915_private *dev_priv;
+       int ret;
+
        if (ring->gem_object == NULL)
                return;
 
+       /* Disable the ring buffer. The ring must be idle at this point */
+       dev_priv = ring->dev->dev_private;
+       ret = intel_wait_ring_buffer(ring, ring->size - 8);
+       I915_WRITE_CTL(ring, 0);
+
        drm_core_ioremapfree(&ring->map, ring->dev);
 
        i915_gem_object_unpin(ring->gem_object);
@@ -693,6 +691,17 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
        struct drm_device *dev = ring->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        unsigned long end;
+       u32 head;
+
+       head = intel_read_status_page(ring, 4);
+       if (head) {
+               ring->head = head & HEAD_ADDR;
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->size;
+               if (ring->space >= n)
+                       return 0;
+       }
 
        trace_i915_ring_wait_begin (dev);
        end = jiffies + 3 * HZ;
@@ -713,6 +722,8 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
                }
 
                msleep(1);
+               if (atomic_read(&dev_priv->mm.wedged))
+                       return -EAGAIN;
        } while (!time_after(jiffies, end));
        trace_i915_ring_wait_end (dev);
        return -EBUSY;