summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsg <jsg@openbsd.org>2013-03-28 11:51:05 +0000
committerjsg <jsg@openbsd.org>2013-03-28 11:51:05 +0000
commit1bbbad48217faa70dd692d60c8f46feb6a6bd461 (patch)
tree79f2c1beb555bd12ec504dbebcc27c4f423ba074
parentaccept and use any protocol specified by the caller. (diff)
downloadwireguard-openbsd-1bbbad48217faa70dd692d60c8f46feb6a6bd461.tar.xz
wireguard-openbsd-1bbbad48217faa70dd692d60c8f46feb6a6bd461.zip
add i915_gem_execbuffer_reserve_object and friends and move
the execbuffer pinning closer to linux
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c31
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.h15
-rw-r--r--sys/dev/pci/drm/i915/i915_gem_execbuffer.c198
3 files changed, 212 insertions, 32 deletions
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index 6100472ece5..885bb0b066f 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.c,v 1.9 2013/03/28 05:13:07 jsg Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.10 2013/03/28 11:51:05 jsg Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -1547,39 +1547,20 @@ inteldrm_wipe_mappings(struct drm_obj *obj)
int
i915_gem_object_pin_and_relocate(struct drm_obj *obj,
struct drm_file *file_priv, struct drm_i915_gem_exec_object2 *entry,
- struct drm_i915_gem_relocation_entry *relocs)
+ struct drm_i915_gem_relocation_entry *relocs, struct intel_ring_buffer *ring)
{
struct drm_device *dev = obj->dev;
struct inteldrm_softc *dev_priv = dev->dev_private;
struct drm_obj *target_obj;
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
bus_space_handle_t bsh;
- int i, ret, needs_fence;
+ int i, ret;
DRM_ASSERT_HELD(obj);
- needs_fence = ((entry->flags & EXEC_OBJECT_NEEDS_FENCE) &&
- obj_priv->tiling_mode != I915_TILING_NONE);
- if (needs_fence)
- atomic_setbits_int(&obj->do_flags, I915_EXEC_NEEDS_FENCE);
-
- /* Choose the GTT offset for our buffer and put it there. */
- ret = i915_gem_object_pin(obj_priv, (u_int32_t)entry->alignment,
- needs_fence);
- if (ret)
- return ret;
-
- if (needs_fence) {
- ret = i915_gem_object_get_fence(obj_priv);
- if (ret)
- return ret;
-
- if (i915_gem_object_pin_fence(obj_priv))
- obj->do_flags |= __EXEC_OBJECT_HAS_FENCE;
- obj_priv->pending_fenced_gpu_access = true;
- }
-
- entry->offset = obj_priv->gtt_offset;
+ ret = i915_gem_execbuffer_reserve_object(obj_priv, ring);
+ if (ret)
+ return (ret);
/* Apply the relocations, using the GTT aperture to avoid cache
* flushing requirements.
diff --git a/sys/dev/pci/drm/i915/i915_drv.h b/sys/dev/pci/drm/i915/i915_drv.h
index c0cdd347e09..3fca3a28d80 100644
--- a/sys/dev/pci/drm/i915/i915_drv.h
+++ b/sys/dev/pci/drm/i915/i915_drv.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.h,v 1.7 2013/03/28 05:13:07 jsg Exp $ */
+/* $OpenBSD: i915_drv.h,v 1.8 2013/03/28 11:51:05 jsg Exp $ */
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
/*
@@ -863,6 +863,8 @@ struct drm_i915_gem_object {
/** This object's place on the active/flushing/inactive lists */
struct list_head ring_list;
struct list_head mm_list;
+ /** This object's place in the batchbuffer or on the eviction list */
+ struct list_head exec_list;
/* GTT binding. */
bus_dmamap_t dmamap;
bus_dma_segment_t *dma_segs;
@@ -937,6 +939,12 @@ struct drm_i915_gem_object {
unsigned int cache_level:2;
+ /**
+ * Used for performing relocations during execbuffer insertion.
+ */
+ unsigned long exec_handle;
+ struct drm_i915_gem_exec_object2 *exec_entry;
+
/** for phy allocated objects */
struct drm_i915_gem_phys_object *phys_obj;
@@ -1080,7 +1088,10 @@ void i915_dispatch_gem_execbuffer(struct intel_ring_buffer *,
struct drm_i915_gem_execbuffer2 *, uint64_t);
int i915_gem_object_pin_and_relocate(struct drm_obj *,
struct drm_file *, struct drm_i915_gem_exec_object2 *,
- struct drm_i915_gem_relocation_entry *);
+ struct drm_i915_gem_relocation_entry *, struct intel_ring_buffer *);
+int i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *,
+ struct intel_ring_buffer *);
+void i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *);
struct drm_obj *i915_gem_find_inactive_object(struct inteldrm_softc *,
size_t);
diff --git a/sys/dev/pci/drm/i915/i915_gem_execbuffer.c b/sys/dev/pci/drm/i915/i915_gem_execbuffer.c
index 6132dc13e15..57714609442 100644
--- a/sys/dev/pci/drm/i915/i915_gem_execbuffer.c
+++ b/sys/dev/pci/drm/i915/i915_gem_execbuffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_gem_execbuffer.c,v 1.1 2013/03/18 12:36:52 jsg Exp $ */
+/* $OpenBSD: i915_gem_execbuffer.c,v 1.2 2013/03/28 11:51:05 jsg Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -62,6 +62,9 @@ void i915_gem_execbuffer_move_to_active(struct drm_obj **, int,
struct intel_ring_buffer *);
void i915_gem_execbuffer_retire_commands(struct drm_device *,
struct drm_file *, struct intel_ring_buffer *);
+int need_reloc_mappable(struct drm_i915_gem_object *);
+int i915_gem_execbuffer_reserve(struct intel_ring_buffer *,
+ struct drm_file *, struct list_head *);
// struct eb_objects {
// eb_create
@@ -69,13 +72,197 @@ void i915_gem_execbuffer_retire_commands(struct drm_device *,
// eb_add_object
// eb_get_object
// eb_destroy
+
+static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
+{
+ return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
+ !obj->map_and_fenceable ||
+ obj->cache_level != I915_CACHE_NONE);
+}
+
// i915_gem_execbuffer_relocate_entry
// i915_gem_execbuffer_relocate_object
// i915_gem_execbuffer_relocate_object_slow
// i915_gem_execbuffer_relocate
-// pin_and_fence_object
-// i915_gem_execbuffer_reserve
-// i915_gem_execbuffer_relocate_slow
+
+#define __EXEC_OBJECT_HAS_PIN (1<<31)
+#define __EXEC_OBJECT_HAS_FENCE (1<<30)
+
+int
+need_reloc_mappable(struct drm_i915_gem_object *obj)
+{
+ struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ return entry->relocation_count && !use_cpu_reloc(obj);
+}
+
+int
+i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
+ struct intel_ring_buffer *ring)
+{
+#ifdef notyet
+ struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+#endif
+ struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+ bool need_fence, need_mappable;
+ int ret;
+
+ need_fence =
+ has_fenced_gpu_access &&
+ entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+ obj->tiling_mode != I915_TILING_NONE;
+ need_mappable = need_fence || need_reloc_mappable(obj);
+
+ ret = i915_gem_object_pin(obj, entry->alignment, need_mappable);
+ if (ret)
+ return ret;
+
+ entry->flags |= __EXEC_OBJECT_HAS_PIN;
+
+ if (has_fenced_gpu_access) {
+ if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
+ ret = i915_gem_object_get_fence(obj);
+ if (ret)
+ return ret;
+
+ if (i915_gem_object_pin_fence(obj))
+ entry->flags |= __EXEC_OBJECT_HAS_FENCE;
+
+ obj->pending_fenced_gpu_access = true;
+ }
+ }
+
+#ifdef notyet
+ /* Ensure ppgtt mapping exists if needed */
+ if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
+ i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
+ obj, obj->cache_level);
+
+ obj->has_aliasing_ppgtt_mapping = 1;
+ }
+#endif
+
+ entry->offset = obj->gtt_offset;
+ return 0;
+}
+
+void
+i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
+{
+ struct drm_i915_gem_exec_object2 *entry;
+
+ if (obj->dmamap == NULL)
+ return;
+
+ entry = obj->exec_entry;
+
+ if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
+ i915_gem_object_unpin_fence(obj);
+
+ if (entry->flags & __EXEC_OBJECT_HAS_PIN)
+ i915_gem_object_unpin(obj);
+
+ entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
+}
+
+int
+i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
+ struct drm_file *file,
+ struct list_head *objects)
+{
+ struct drm_i915_gem_object *obj;
+ struct list_head ordered_objects;
+ bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+ int retry;
+
+ INIT_LIST_HEAD(&ordered_objects);
+ while (!list_empty(objects)) {
+ struct drm_i915_gem_exec_object2 *entry;
+ bool need_fence, need_mappable;
+
+ obj = list_first_entry(objects,
+ struct drm_i915_gem_object,
+ exec_list);
+ entry = obj->exec_entry;
+
+ need_fence =
+ has_fenced_gpu_access &&
+ entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+ obj->tiling_mode != I915_TILING_NONE;
+ need_mappable = need_fence || need_reloc_mappable(obj);
+
+ if (need_mappable)
+ list_move(&obj->exec_list, &ordered_objects);
+ else
+ list_move_tail(&obj->exec_list, &ordered_objects);
+
+ obj->base.pending_read_domains = 0;
+ obj->base.pending_write_domain = 0;
+ obj->pending_fenced_gpu_access = false;
+ }
+ list_splice(&ordered_objects, objects);
+
+ /* Attempt to pin all of the buffers into the GTT.
+ * This is done in 3 phases:
+ *
+ * 1a. Unbind all objects that do not match the GTT constraints for
+ * the execbuffer (fenceable, mappable, alignment etc).
+ * 1b. Increment pin count for already bound objects.
+ * 2. Bind new objects.
+ * 3. Decrement pin count.
+ *
+ * This avoid unnecessary unbinding of later objects in order to make
+ * room for the earlier objects *unless* we need to defragment.
+ */
+ retry = 0;
+ do {
+ int ret = 0;
+
+ /* Unbind any ill-fitting objects or pin. */
+ list_for_each_entry(obj, objects, exec_list) {
+ struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ bool need_fence, need_mappable;
+
+ if (obj->dmamap == NULL)
+ continue;
+
+ need_fence =
+ has_fenced_gpu_access &&
+ entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+ obj->tiling_mode != I915_TILING_NONE;
+ need_mappable = need_fence || need_reloc_mappable(obj);
+
+ if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||
+ (need_mappable && !obj->map_and_fenceable))
+ ret = i915_gem_object_unbind(obj);
+ else
+ ret = i915_gem_execbuffer_reserve_object(obj, ring);
+ if (ret)
+ goto err;
+ }
+
+ /* Bind fresh objects */
+ list_for_each_entry(obj, objects, exec_list) {
+ if (obj->dmamap != NULL)
+ continue;
+
+ ret = i915_gem_execbuffer_reserve_object(obj, ring);
+ if (ret)
+ goto err;
+ }
+
+err: /* Decrement pin count for bound objects */
+ list_for_each_entry(obj, objects, exec_list)
+ i915_gem_execbuffer_unreserve_object(obj);
+
+ if (ret != -ENOSPC || retry++)
+ return ret;
+
+ ret = i915_gem_evict_everything(ring->dev->dev_private);
+ if (ret)
+ return ret;
+ } while (1);
+}
int
i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
@@ -385,8 +572,9 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
object_list[i]->pending_write_domain = 0;
to_intel_bo(object_list[i])->pending_fenced_gpu_access = false;
drm_hold_object(object_list[i]);
+ to_intel_bo(object_list[i])->exec_entry = &exec_list[i];
ret = i915_gem_object_pin_and_relocate(object_list[i],
- file_priv, &exec_list[i], &relocs[reloc_index]);
+ file_priv, &exec_list[i], &relocs[reloc_index], ring);
if (ret) {
drm_unhold_object(object_list[i]);
break;