mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 16:37:50 +00:00
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: Sinclair Yeh <syeh@vmware.com> Reviewed-by: Deepak Singh Rawat <drawat@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
This commit is contained in:
parent
2cfa0bb25d
commit
5858511646
3 changed files with 71 additions and 2 deletions
|
@ -24,6 +24,7 @@
|
||||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
#include <linux/sync_file.h>
|
||||||
|
|
||||||
#include "vmwgfx_drv.h"
|
#include "vmwgfx_drv.h"
|
||||||
#include "vmwgfx_reg.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[] = {
|
static const size_t copy_offset[] = {
|
||||||
offsetof(struct drm_vmw_execbuf_arg, context_handle),
|
offsetof(struct drm_vmw_execbuf_arg, context_handle),
|
||||||
sizeof(struct drm_vmw_execbuf_arg)};
|
sizeof(struct drm_vmw_execbuf_arg)};
|
||||||
|
struct dma_fence *in_fence = NULL;
|
||||||
|
|
||||||
if (unlikely(size < copy_offset[0])) {
|
if (unlikely(size < copy_offset[0])) {
|
||||||
DRM_ERROR("Invalid command size, ioctl %d\n",
|
DRM_ERROR("Invalid command size, ioctl %d\n",
|
||||||
|
@ -4453,6 +4455,21 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
|
||||||
break;
|
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);
|
ret = ttm_read_lock(&dev_priv->reservation_sem, true);
|
||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4465,9 +4482,12 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,
|
||||||
NULL);
|
NULL);
|
||||||
ttm_read_unlock(&dev_priv->reservation_sem);
|
ttm_read_unlock(&dev_priv->reservation_sem);
|
||||||
if (unlikely(ret != 0))
|
if (unlikely(ret != 0))
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
vmw_kms_cursor_post_execbuf(dev_priv);
|
vmw_kms_cursor_post_execbuf(dev_priv);
|
||||||
|
|
||||||
return 0;
|
out:
|
||||||
|
if (in_fence)
|
||||||
|
dma_fence_put(in_fence);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* vmw_fence_fifo_down - signal all unsignaled fence objects.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#ifndef _VMWGFX_FENCE_H_
|
#ifndef _VMWGFX_FENCE_H_
|
||||||
|
|
||||||
#include <linux/dma-fence.h>
|
#include <linux/dma-fence.h>
|
||||||
|
#include <linux/dma-fence-array.h>
|
||||||
|
|
||||||
#define VMW_FENCE_WAIT_TIMEOUT (5*HZ)
|
#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,
|
struct vmw_fence_obj **p_fence,
|
||||||
uint32_t *p_handle);
|
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_up(struct vmw_fence_manager *fman);
|
||||||
|
|
||||||
extern void vmw_fence_fifo_down(struct vmw_fence_manager *fman);
|
extern void vmw_fence_fifo_down(struct vmw_fence_manager *fman);
|
||||||
|
|
Loading…
Reference in a new issue