DRM_MEMORYBARRIER();
}
- rep.ret = drm_bo_handle_validate(file_priv, req->bo_req.handle,
- req->bo_req.flags, req->bo_req.mask,
- req->bo_req.hint,
- req->bo_req.fence_class, 0,
- &rep.bo_info,
- &buffers[buf_count].buffer);
+ ret = drm_bo_handle_validate(file_priv, req->bo_req.handle,
+ req->bo_req.flags, req->bo_req.mask,
+ req->bo_req.hint,
+ req->bo_req.fence_class, 0,
+ &item->rep,
+ &item->buffer);
- if (rep.ret) {
- DRM_ERROR("error on handle validate %d\n", rep.ret);
+ if (ret) {
+ DRM_ERROR("error on handle validate %d\n", ret);
goto out_err;
}
- struct drm_device *dev = file_priv->head->dev;
+
+ buf_count++;
+
+ ret = i915_check_presumed(&arg, item->buffer,
+ (uint32_t __user *)
+ (unsigned long) data,
+ &item->presumed_offset_correct);
+ if (ret)
+ goto out_err;
+
+ data = arg.next;
+ } while (data != 0);
+ out_err:
+ *num_buffers = buf_count;
+ item->ret = (ret != -EAGAIN) ? ret : 0;
+ return ret;
+ }
+
+
+ /*
+ * Remove all buffers from the unfenced list.
+ * If the execbuffer operation was aborted, for example due to a signal,
+ * this also make sure that buffers retain their original state and
+ * fence pointers.
+ * Copy back buffer information to user-space unless we were interrupted
+ * by a signal. In which case the IOCTL must be rerun.
+ */
+
+ static int i915_handle_copyback(struct drm_device *dev,
+ struct drm_i915_validate_buffer *buffers,
+ unsigned int num_buffers, int ret)
+ {
+ int err = ret;
+ int i;
+ struct drm_i915_op_arg arg;
+
+ if (ret)
+ drm_putback_buffer_objects(dev);
+
+ if (ret != -EAGAIN) {
+ for (i = 0; i < num_buffers; ++i) {
+ arg.handled = 1;
+ arg.d.rep.ret = buffers->ret;
+ arg.d.rep.bo_info = buffers->rep;
+ if (__copy_to_user(buffers->data, &arg, sizeof(arg)))
+ err = -EFAULT;
+ buffers++;
+ }
+ }
+
+ return err;
+ }
+
+ /*
+ * Create a fence object, and if that fails, pretend that everything is
+ * OK and just idle the GPU.
+ */
+
+ void i915_fence_or_sync(struct drm_file *file_priv,
+ uint32_t fence_flags,
+ struct drm_fence_arg *fence_arg,
+ struct drm_fence_object **fence_p)
+ {
++ struct drm_device *dev = file_priv->minor->dev;
+ int ret;
+ struct drm_fence_object *fence;
+
+ ret = drm_fence_buffer_objects(dev, NULL, fence_flags,
+ NULL, &fence);
+
+ if (ret) {
+
/*
- * If the user provided a presumed offset hint, check whether
- * the buffer is in the same place, if so, relocations relative to
- * this buffer need not be performed
+ * Fence creation failed.
+ * Fall back to synchronous operation and idle the engine.
*/
- if ((req->bo_req.hint & DRM_BO_HINT_PRESUMED_OFFSET) &&
- buffers[buf_count].buffer->offset == req->bo_req.presumed_offset) {
- buffers[buf_count].presumed_offset_correct = 1;
- }
- next = arg.next;
- arg.handled = 1;
- arg.d.rep = rep;
+ (void) i915_emit_mi_flush(dev, MI_READ_FLUSH);
+ (void) i915_quiescent(dev);
- if (copy_to_user((void __user *)(unsigned long)data, &arg, sizeof(arg)))
- return -EFAULT;
+ if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) {
- data = next;
- buf_count++;
+ /*
+ * Communicate to user-space that
+ * fence creation has failed and that
+ * the engine is idle.
+ */
- } while (next != 0);
- *num_buffers = buf_count;
- return 0;
- out_err:
- mutex_lock(&dev->struct_mutex);
- i915_dereference_buffers_locked(buffers, buf_count);
- mutex_unlock(&dev->struct_mutex);
- *num_buffers = 0;
- return (ret) ? ret : rep.ret;
+ fence_arg->handle = ~0;
+ fence_arg->error = ret;
+ }
+
+ drm_putback_buffer_objects(dev);
+ if (fence_p)
+ *fence_p = NULL;
+ return;
+ }
+
+ if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) {
+
+ ret = drm_fence_add_user_object(file_priv, fence,
+ fence_flags &
+ DRM_FENCE_FLAG_SHAREABLE);
+ if (!ret)
+ drm_fence_fill_arg(fence, fence_arg);
+ else {
+ /*
+ * Fence user object creation failed.
+ * We must idle the engine here as well, as user-
+ * space expects a fence object to wait on. Since we
+ * have a fence object we wait for it to signal
+ * to indicate engine "sufficiently" idle.
+ */
+
+ (void) drm_fence_object_wait(fence, 0, 1,
+ fence->type);
+ drm_fence_usage_deref_unlocked(&fence);
+ fence_arg->handle = ~0;
+ fence_arg->error = ret;
+ }
+ }
+
+ if (fence_p)
+ *fence_p = fence;
+ else if (fence)
+ drm_fence_usage_deref_unlocked(&fence);
}
+
static int i915_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{