Skip to content

Commit

Permalink
drm/vmwgfx: Add support for imported Fence File Descriptor
Browse files Browse the repository at this point in the history
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: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Deepak Singh Rawat <drawat@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
  • Loading branch information
Sinclair Yeh committed Aug 28, 2017
1 parent 2cfa0bb commit 5858511
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
24 changes: 22 additions & 2 deletions drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include <linux/sync_file.h>

#include "vmwgfx_drv.h"
#include "vmwgfx_reg.h"
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand All @@ -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 changes: 45 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,51 @@ int vmw_user_fence_create(struct drm_file *file_priv,
}


/**
* 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.
*/
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 5858511

Please sign in to comment.