Commit 58585116 authored by Sinclair Yeh's avatar Sinclair Yeh
Browse files

drm/vmwgfx: Add support for imported Fence File Descriptor



This allows vmwgfx to wait on a fence created by another
device.

v2:
* Remove special handling for vmwgfx fence and just use dma_fence_wait()
* Use interruptible waits
* Added function documentation

Signed-off-by: default avatarSinclair Yeh <syeh@vmware.com>
Reviewed-by: default avatarDeepak Singh Rawat <drawat@vmware.com>
Reviewed-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
parent 2cfa0bb2
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/
#include <linux/sync_file.h>

#include "vmwgfx_drv.h"
#include "vmwgfx_reg.h"
@@ -4414,6 +4415,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
	static const size_t copy_offset[] = {
		offsetof(struct drm_vmw_execbuf_arg, context_handle),
		sizeof(struct drm_vmw_execbuf_arg)};
	struct dma_fence *in_fence = NULL;

	if (unlikely(size < copy_offset[0])) {
		DRM_ERROR("Invalid command size, ioctl %d\n",
@@ -4453,6 +4455,21 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
		break;
	}


	/* If imported a fence FD from elsewhere, then wait on it */
	if (arg.flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) {
		in_fence = sync_file_get_fence(arg.imported_fence_fd);

		if (!in_fence) {
			DRM_ERROR("Cannot get imported fence\n");
			return -EINVAL;
		}

		ret = vmw_wait_dma_fence(dev_priv->fman, in_fence);
		if (ret)
			goto out;
	}

	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
	if (unlikely(ret != 0))
		return ret;
@@ -4465,9 +4482,12 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
				  NULL);
	ttm_read_unlock(&dev_priv->reservation_sem);
	if (unlikely(ret != 0))
		return ret;
		goto out;

	vmw_kms_cursor_post_execbuf(dev_priv);

	return 0;
out:
	if (in_fence)
		dma_fence_put(in_fence);
	return ret;
}
+45 −0
Original line number Diff line number Diff line
@@ -644,6 +644,51 @@ out_no_object:
}


/**
 * vmw_wait_dma_fence - Wait for a dma fence
 *
 * @fman: pointer to a fence manager
 * @fence: DMA fence to wait on
 *
 * This function handles the case when the fence is actually a fence
 * array.  If that's the case, it'll wait on each of the child fence
 */
int vmw_wait_dma_fence(struct vmw_fence_manager *fman,
		       struct dma_fence *fence)
{
	struct dma_fence_array *fence_array;
	int ret = 0;
	int i;


	if (dma_fence_is_signaled(fence))
		return 0;

	if (!dma_fence_is_array(fence))
		return dma_fence_wait(fence, true);

	/* From i915: Note that if the fence-array was created in
	 * signal-on-any mode, we should *not* decompose it into its individual
	 * fences. However, we don't currently store which mode the fence-array
	 * is operating in. Fortunately, the only user of signal-on-any is
	 * private to amdgpu and we should not see any incoming fence-array
	 * from sync-file being in signal-on-any mode.
	 */

	fence_array = to_dma_fence_array(fence);
	for (i = 0; i < fence_array->num_fences; i++) {
		struct dma_fence *child = fence_array->fences[i];

		ret = dma_fence_wait(child, true);

		if (ret < 0)
			return ret;
	}

	return 0;
}


/**
 * vmw_fence_fifo_down - signal all unsignaled fence objects.
 */
+4 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#ifndef _VMWGFX_FENCE_H_

#include <linux/dma-fence.h>
#include <linux/dma-fence-array.h>

#define VMW_FENCE_WAIT_TIMEOUT (5*HZ)

@@ -102,6 +103,9 @@ extern int vmw_user_fence_create(struct drm_file *file_priv,
				 struct vmw_fence_obj **p_fence,
				 uint32_t *p_handle);

extern int vmw_wait_dma_fence(struct vmw_fence_manager *fman,
			      struct dma_fence *fence);

extern void vmw_fence_fifo_up(struct vmw_fence_manager *fman);

extern void vmw_fence_fifo_down(struct vmw_fence_manager *fman);