+/**
+ * Moves a single object to the GTT read, and possibly write domain.
+ *
+ * This function returns when the move is complete, including waiting on
+ * flushes to occur.
+ */
+static int
+i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ uint32_t flush_domains;
+
+ /* Figure out what GPU domains we need to flush or invalidate for
+ * moving to GTT.
+ */
+ flush_domains = obj->write_domain & I915_GEM_GPU_DOMAINS;
+
+ /* Queue the GPU write cache flushing we need. */
+ if (flush_domains != 0) {
+ uint32_t seqno;
+
+ obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
+ i915_gem_flush(dev, 0, flush_domains);
+ seqno = i915_add_request(dev, flush_domains);
+ i915_gem_object_move_to_active(obj, seqno);
+ }
+
+ /* Wait on any GPU rendering and flushing to occur. */
+ if (obj_priv->active) {
+ int ret;
+
+ ret = i915_wait_request(dev, obj_priv->last_rendering_seqno);
+ if (ret != 0)
+ return ret;
+ }
+
+ /* If we're writing through the GTT domain, then CPU and GPU caches
+ * will need to be invalidated at next use.
+ */
+ if (write)
+ obj->read_domains &= ~(I915_GEM_GPU_DOMAINS |
+ I915_GEM_DOMAIN_CPU);
+
+ /* Flush the CPU domain if it's dirty. */
+ if (obj->write_domain & I915_GEM_DOMAIN_CPU) {
+ i915_gem_clflush_object(obj);
+ drm_agp_chipset_flush(dev);
+
+ obj->write_domain &= ~I915_GEM_DOMAIN_CPU;
+ }
+
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
+ */
+ BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+ obj->read_domains |= I915_GEM_DOMAIN_GTT;
+ if (write)
+ obj->write_domain = I915_GEM_DOMAIN_GTT;
+
+ return 0;
+}
+