Commit 1cc16538 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: make amdgpu_user_wait_ioctl more resilent v2



When the memory allocated by userspace isn't sufficient for all the
fences then just wait on them instead of returning an error.

v2: use correct variable as pointed out by Sunil

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarSunil Khatri <sunil.khatri@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 79b38858
Loading
Loading
Loading
Loading
+27 −21
Original line number Diff line number Diff line
@@ -705,7 +705,7 @@ amdgpu_userq_wait_count_fences(struct drm_file *filp,
			num_fences++;
	}

	wait_info->num_fences = num_fences;
	wait_info->num_fences = min(num_fences, USHRT_MAX);
	r = 0;

error_unlock:
@@ -714,6 +714,19 @@ amdgpu_userq_wait_count_fences(struct drm_file *filp,
	return r;
}

static int
amdgpu_userq_wait_add_fence(struct drm_amdgpu_userq_wait *wait_info,
			    struct dma_fence **fences, unsigned int *num_fences,
			    struct dma_fence *fence)
{
	/* As fallback shouldn't userspace allocate enough space */
	if (*num_fences >= wait_info->num_fences)
		return dma_fence_wait(fence, true);

	fences[(*num_fences)++] = dma_fence_get(fence);
	return 0;
}

static int
amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
				    struct drm_amdgpu_userq_wait *wait_info,
@@ -757,13 +770,12 @@ amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
			goto free_fences;

		dma_fence_unwrap_for_each(f, &iter, fence) {
			if (num_fences >= wait_info->num_fences) {
				r = -EINVAL;
			r = amdgpu_userq_wait_add_fence(wait_info, fences,
							&num_fences, f);
			if (r) {
				dma_fence_put(fence);
				goto free_fences;
			}

			fences[num_fences++] = dma_fence_get(f);
		}

		dma_fence_put(fence);
@@ -780,14 +792,12 @@ amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
		if (r)
			goto free_fences;

		if (num_fences >= wait_info->num_fences) {
		r = amdgpu_userq_wait_add_fence(wait_info, fences,
						&num_fences, fence);
		dma_fence_put(fence);
			r = -EINVAL;
		if (r)
			goto free_fences;
		}

		/* Give the reference to the fence array */
		fences[num_fences++] = fence;
	}

	/* Lock all the GEM objects */
@@ -817,13 +827,11 @@ amdgpu_userq_wait_return_fence_info(struct drm_file *filp,

		dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
					DMA_RESV_USAGE_READ, fence) {
			if (num_fences >= wait_info->num_fences) {
				r = -EINVAL;
			r = amdgpu_userq_wait_add_fence(wait_info, fences,
							&num_fences, fence);
			if (r)
				goto error_unlock;
		}

			fences[num_fences++] = dma_fence_get(fence);
		}
	}

	/* Retrieve GEM write objects fence */
@@ -833,13 +841,11 @@ amdgpu_userq_wait_return_fence_info(struct drm_file *filp,

		dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
					DMA_RESV_USAGE_WRITE, fence) {
			if (num_fences >= wait_info->num_fences) {
				r = -EINVAL;
			r = amdgpu_userq_wait_add_fence(wait_info, fences,
							&num_fences, fence);
			if (r)
				goto error_unlock;
		}

			fences[num_fences++] = dma_fence_get(fence);
		}
	}

	drm_exec_fini(&exec);