+VkResult
+anv_device_execbuf(struct anv_device *device,
+ struct drm_i915_gem_execbuffer2 *execbuf,
+ struct anv_bo **execbuf_bos)
+{
+ int ret = anv_gem_execbuffer(device, execbuf);
+ if (ret != 0) {
+ /* We don't know the real error. */
+ device->lost = true;
+ return vk_errorf(VK_ERROR_DEVICE_LOST, "execbuf2 failed: %m");
+ }
+
+ struct drm_i915_gem_exec_object2 *objects =
+ (void *)(uintptr_t)execbuf->buffers_ptr;
+ for (uint32_t k = 0; k < execbuf->buffer_count; k++)
+ execbuf_bos[k]->offset = objects[k].offset;
+
+ return VK_SUCCESS;
+}
+
+VkResult
+anv_device_query_status(struct anv_device *device)
+{
+ /* This isn't likely as most of the callers of this function already check
+ * for it. However, it doesn't hurt to check and it potentially lets us
+ * avoid an ioctl.
+ */
+ if (unlikely(device->lost))
+ return VK_ERROR_DEVICE_LOST;
+
+ uint32_t active, pending;
+ int ret = anv_gem_gpu_get_reset_stats(device, &active, &pending);
+ if (ret == -1) {
+ /* We don't know the real error. */
+ device->lost = true;
+ return vk_errorf(VK_ERROR_DEVICE_LOST, "get_reset_stats failed: %m");
+ }
+
+ if (active) {
+ device->lost = true;
+ return vk_errorf(VK_ERROR_DEVICE_LOST,
+ "GPU hung on one of our command buffers");
+ } else if (pending) {
+ device->lost = true;
+ return vk_errorf(VK_ERROR_DEVICE_LOST,
+ "GPU hung with commands in-flight");
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult
+anv_device_bo_busy(struct anv_device *device, struct anv_bo *bo)
+{
+ /* Note: This only returns whether or not the BO is in use by an i915 GPU.
+ * Other usages of the BO (such as on different hardware) will not be
+ * flagged as "busy" by this ioctl. Use with care.
+ */
+ int ret = anv_gem_busy(device, bo->gem_handle);
+ if (ret == 1) {
+ return VK_NOT_READY;
+ } else if (ret == -1) {
+ /* We don't know the real error. */
+ device->lost = true;
+ return vk_errorf(VK_ERROR_DEVICE_LOST, "gem wait failed: %m");
+ }
+
+ /* Query for device status after the busy call. If the BO we're checking
+ * got caught in a GPU hang we don't want to return VK_SUCCESS to the
+ * client because it clearly doesn't have valid data. Yes, this most
+ * likely means an ioctl, but we just did an ioctl to query the busy status
+ * so it's no great loss.
+ */
+ return anv_device_query_status(device);
+}
+
+VkResult
+anv_device_wait(struct anv_device *device, struct anv_bo *bo,
+ int64_t timeout)
+{
+ int ret = anv_gem_wait(device, bo->gem_handle, &timeout);
+ if (ret == -1 && errno == ETIME) {
+ return VK_TIMEOUT;
+ } else if (ret == -1) {
+ /* We don't know the real error. */
+ device->lost = true;
+ return vk_errorf(VK_ERROR_DEVICE_LOST, "gem wait failed: %m");
+ }
+
+ /* Query for device status after the wait. If the BO we're waiting on got
+ * caught in a GPU hang we don't want to return VK_SUCCESS to the client
+ * because it clearly doesn't have valid data. Yes, this most likely means
+ * an ioctl, but we just did an ioctl to wait so it's no great loss.
+ */
+ return anv_device_query_status(device);
+}
+