summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm/i915_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/drm/i915_gem.c')
-rw-r--r--sys/dev/pci/drm/i915_gem.c204
1 files changed, 93 insertions, 111 deletions
diff --git a/sys/dev/pci/drm/i915_gem.c b/sys/dev/pci/drm/i915_gem.c
index 49e957f937e..3ff807421ee 100644
--- a/sys/dev/pci/drm/i915_gem.c
+++ b/sys/dev/pci/drm/i915_gem.c
@@ -74,6 +74,8 @@ void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *);
int i915_gem_gtt_rebind_object(struct drm_i915_gem_object *,
enum i915_cache_level);
void i915_gem_request_remove_from_client(struct drm_i915_gem_request *);
+int i915_gem_object_flush_active(struct drm_i915_gem_object *);
+int i915_gem_check_olr(struct intel_ring_buffer *, u32);
extern int ticks;
@@ -406,7 +408,24 @@ i915_gem_check_wedge(struct inteldrm_softc *dev_priv,
return 0;
}
-// i915_gem_check_olr
+/*
+ * Compare seqno against outstanding lazy request. Emit a request if they are
+ * equal.
+ */
+int
+i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
+{
+ int ret;
+
+// BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex));
+
+ ret = 0;
+ if (seqno == ring->outstanding_lazy_request)
+ ret = i915_add_request(ring, NULL, NULL);
+
+ return ret;
+}
+
// __wait_seqno
/**
@@ -1112,7 +1131,6 @@ i915_gem_reset_ring_lists(drm_i915_private_t *dev_priv,
struct drm_i915_gem_object,
ring_list);
- obj->base.write_domain = 0;
i915_gem_object_move_to_inactive(obj);
}
}
@@ -1217,10 +1235,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
if (!i915_seqno_passed(seqno, obj->last_read_seqno))
break;
- if (obj->base.write_domain != 0)
- i915_gem_object_move_off_active(obj);
- else
- i915_gem_object_move_to_inactive(obj);
+ i915_gem_object_move_to_inactive(obj);
}
}
@@ -1235,9 +1250,73 @@ i915_gem_retire_requests(struct inteldrm_softc *dev_priv)
}
// i915_gem_retire_work_handler
-// i915_gem_object_flush_active
+
+/**
+ * Ensures that an object will eventually get non-busy by flushing any required
+ * write domains, emitting any outstanding lazy request and retiring and
+ * completed requests.
+ */
+int
+i915_gem_object_flush_active(struct drm_i915_gem_object *obj)
+{
+ int ret;
+
+ if (obj->active) {
+ ret = i915_gem_check_olr(obj->ring, obj->last_read_seqno);
+ if (ret)
+ return ret;
+
+ i915_gem_retire_requests_ring(obj->ring);
+ }
+
+ return 0;
+}
+
// i915_gem_wait_ioctl
-// i915_gem_object_sync
+
+/**
+ * i915_gem_object_sync - sync an object to a ring.
+ *
+ * @obj: object which may be in use on another ring.
+ * @to: ring we wish to use the object on. May be NULL.
+ *
+ * This code is meant to abstract object synchronization with the GPU.
+ * Calling with NULL implies synchronizing the object with the CPU
+ * rather than a particular GPU ring.
+ *
+ * Returns 0 if successful, else propagates up the lower layer error.
+ */
+int
+i915_gem_object_sync(struct drm_i915_gem_object *obj,
+ struct intel_ring_buffer *to)
+{
+ struct intel_ring_buffer *from = obj->ring;
+ u32 seqno;
+ int ret, idx;
+
+ if (from == NULL || to == from)
+ return 0;
+
+ if (to == NULL || !i915_semaphore_is_enabled(obj->base.dev))
+ return i915_gem_object_wait_rendering(obj, false);
+
+ idx = intel_ring_sync_index(from, to);
+
+ seqno = obj->last_read_seqno;
+ if (seqno <= from->sync_seqno[idx])
+ return 0;
+
+ if (seqno == from->outstanding_lazy_request) {
+ ret = i915_add_request(from, NULL, &seqno);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ from->sync_seqno[idx] = seqno;
+
+ return to->sync_to(to, from, seqno);
+}
void
i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
@@ -1302,22 +1381,6 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
i915_gem_object_finish_gtt(obj);
- /* Move the object to the CPU domain to ensure that
- * any possible CPU writes while it's not in the GTT
- * are flushed when we go to remap it.
- */
- if (ret == 0)
- ret = i915_gem_object_set_to_cpu_domain(obj, 1);
- if (ret == ERESTART || ret == EINTR)
- return ret;
- if (ret) {
- /* In the event of a disaster, abandon all caches and
- * hope for the best.
- */
- i915_gem_clflush_object(obj);
- obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
- }
-
/* release the fence reg _after_ flushing */
ret = i915_gem_object_put_fence(obj);
if (ret == ERESTART || ret == EINTR)
@@ -1356,25 +1419,6 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
}
int
-i915_gem_flush_ring(struct intel_ring_buffer *ring,
- uint32_t invalidate_domains,
- uint32_t flush_domains)
-{
- int ret;
-
- if (((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) == 0)
- return 0;
-
-// trace_i915_gem_ring_flush(ring, invalidate_domains, flush_domains);
-
- ret = ring->flush(ring, invalidate_domains, flush_domains);
- if (ret)
- return ret;
-
- return 0;
-}
-
-int
i915_gpu_idle(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -1571,19 +1615,8 @@ i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
int
i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
{
- int ret;
-
- if (obj->fenced_gpu_access) {
- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
- ret = i915_gem_flush_ring(obj->ring, 0,
- obj->base.write_domain);
- if (ret)
- return ret;
- }
- }
-
if (obj->last_fenced_seqno) {
- ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno);
+ int ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno);
if (ret)
return ret;
@@ -1901,17 +1934,6 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
#endif
}
-/** Flushes any GPU write domain for the object if it's dirty. */
-int
-i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
-{
- if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
- return 0;
-
- /* Queue the GPU write cache flushing we need. */
- return i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
-}
-
/** Flushes the CPU write domain for the object if it's dirty. */
void
i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
@@ -1955,10 +1977,6 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, int write)
if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
return 0;
- ret = i915_gem_object_flush_gpu_write_domain(obj);
- if (ret)
- return ret;
-
ret = i915_gem_object_wait_rendering(obj, !write);
if (ret)
return ret;
@@ -2078,13 +2096,9 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
// u32 old_read_domains, old_write_domain;
int ret;
- ret = i915_gem_object_flush_gpu_write_domain(obj);
- if (ret)
- return ret;
-
if (pipelined != obj->ring) {
- ret = i915_gem_object_wait_rendering(obj, false);
- if (ret == -ERESTART || ret == -EINTR)
+ ret = i915_gem_object_sync(obj, pipelined);
+ if (ret)
return (ret);
}
@@ -2117,7 +2131,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
/* It should now be out of any other write domains, and we can update
* the domain values for our changes.
*/
- BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+ obj->base.write_domain = 0;
obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
// trace_i915_gem_object_change_domain(obj,
@@ -2135,12 +2149,6 @@ i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
return 0;
- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
- ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
- if (ret)
- return ret;
- }
-
ret = i915_gem_object_wait_rendering(obj, false);
if (ret)
return ret;
@@ -2167,11 +2175,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, int write)
if (obj->base.write_domain == I915_GEM_DOMAIN_CPU)
return 0;
- ret = i915_gem_object_flush_gpu_write_domain(obj);
- if (ret)
- return ret;
-
- ret = i915_gem_object_wait_rendering(obj, false);
+ ret = i915_gem_object_wait_rendering(obj, !write);
if (ret)
return ret;
@@ -2475,30 +2479,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
return (EBADF);
}
+ ret = i915_gem_object_flush_active(obj);
args->busy = obj->active;
- if (args->busy) {
- /*
- * Unconditionally flush objects write domain if they are
- * busy. The fact userland is calling this ioctl means that
- * it wants to use this buffer sooner rather than later, so
- * flushing now shoul reduce latency.
- */
- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
- ret = i915_gem_flush_ring(obj->ring,
- 0, obj->base.write_domain);
- } else if (obj->ring->outstanding_lazy_request ==
- obj->last_read_seqno) {
- i915_add_request(obj->ring, NULL, NULL);
- }
-
- /*
- * Update the active list after the flush otherwise this is
- * only updated on a delayed timer. Updating now reduces
- * working set size.
- */
- i915_gem_retire_requests_ring(obj->ring);
- args->busy = obj->active;
- }
drm_gem_object_unreference(&obj->base);
return ret;